Rによる包括的なデータ分析レポート:エンドツーエンドのプロジェクト全体
これはRチュートリアルの最終レッスンです。これまでの29のレッスンで学んだすべての内容を統合し、完全なエンドツーエンドのプロジェクトを作成します。データの読み込みからクリーニング、探索的データ分析(EDA)の実施、モデルの構築、結果の可視化、レポートの作成に至るまで、このレッスンではデータアナリストの典型的な1日の業務をシミュレートします。
このレッスンを修了すると、データサイエンスの就職面接用のポートフォリオレベルで、Rを用いたデータ分析プロジェクトを独力で完遂できるようになります。
1. 学習内容
- 6段階のエンドツーエンドのプロジェクト(データ → クリーニング → 探索的データ分析(EDA) → モデリング → 可視化 → レポート作成)
- 以下のライブラリを幅広く活用:readr + tidyr + dplyr + ggplot2 + broom + rmarkdown
- R Markdownはレポートを自動的に生成します
- saveRDS の永続化とモデルのデプロイ
- PDF/HTMLレポートを生成する
- 実践ガイド:顧客行動分析に関する包括的レポート
2. データアナリストの1日
(1) 課題:データをレポートにまとめるのに3日かかる
アリスはデータアナリストで、2024年の顧客行動を分析し、上司に包括的なレポートを提出するという任務を任されています。
従来のプロセス:Excelデータをインポート → データを整理 → Excelのピボットテーブルを作成 → グラフを作成 → PowerPointに貼り付け → 分析結果を記述 → 1週間後に上司から確認を求められる。
(2) Rを用いた解決策
# 1. One line R Markdown Report
rmarkdown::render('customer_analysis.Rmd')
1行のコード → 完全なHTML/PDFレポート(コード、結果、グラフ、分析を含む)。
3. エンドツーエンド・プロジェクトの6つの段階
graph TB
A[1. Data Loading] --> B[2. Data Cleaning]
B --> C[3. EDA Explore]
C --> D[4. Descriptive Statistics]
D --> E[5. Modeling and Analysis]
E --> F[6. Visualization and Reporting]
A --> A1[readr/DBI]
B --> B1[tidyr/stringr]
C --> C1[skimr/GGally]
D --> D1[dplyr summary]
E --> E1[lm/glm]
F --> F1[ggplot2/Rmd]
style A fill:#fff3cd
style B fill:#cce5ff
style C fill:#d4edda
style D fill:#f8d7da
style E fill:#e1d4ff
style F fill:#ffe1d4
(1) 6段階の目標
| フェーズ | 目的 | 成果 |
|---|---|---|
| 1. データの読み込み | データの読み取り | tibble |
| 2. データクレンジング | 欠損値・外れ値・重複値の処理 | tibbleのクレンジング |
| 3. EDA | 分布・関係の探索 | グラフと統計 |
| 4. 記述統計 | 主要指標 | 概要表 |
| 5. モデリング | 回帰・分類・クラスタリング | モデルオブジェクト |
| 6. レポート | 統合・分析 | HTML/PDF |
4. 実践編:顧客行動のエンドツーエンド分析プロジェクト
(1) Rスクリプトの全文
# ============================================
# Customer Behavior Analysis - End-to-End Projects
# Stage: 1. Data Loading -> 6. Report Output
# ============================================
library(readr)
library(dplyr)
library(tidyr)
library(stringr)
library(lubridate)
library(ggplot2)
library(broom)
library(skimr)
# ========== Stage 1: Data Loading ==========
cat('=== Stage 1: Data Loading ===\n')
set.seed(42)
n <- 2000
customers_raw <- tibble(
customer_id = 1:n,
age = round(rnorm(n, 35, 12)),
gender = sample(c('M', 'F'), n, replace = TRUE),
city = sample(c('Beijing', 'Shanghai', 'Guangzhou', 'Shenzhen', 'Hangzhou'), n, replace = TRUE),
register_date = sample(seq(as.Date('2023-01-01'),
as.Date('2024-06-30'), by = 'day'), n, replace = TRUE),
monthly_visits = round(rnorm(n, 10, 5)),
avg_order_value = round(rnorm(n, 200, 80)),
support_calls = sample(0:10, n, replace = TRUE),
plan = sample(c('Basics', 'Advanced', 'Company'), n, replace = TRUE,
prob = c(0.5, 0.3, 0.2))
) |>
mutate(
logit_p = -2 + 0.02 * age - 0.05 * monthly_visits + 0.2 * support_calls,
p = 1 / (1 + exp(-logit_p)),
churn = rbinom(n, 1, p)
) |>
select(-logit_p, -p) |>
mutate(
age = ifelse(row_number() %in% sample(n, 10), NA, age),
avg_order_value = ifelse(row_number() %in% sample(n, 5), -999, avg_order_value),
register_date = ifelse(row_number() %in% sample(n, 8), NA, register_date)
)
write_csv(customers_raw, 'customer_raw.csv')
cat('Loaded', nrow(customers_raw), 'Raw Data Row\n\n')
# ========== Stage 2: Data Cleaning ==========
cat('=== Stage 2: Data Cleaning ===\n')
customers <- customers_raw |>
janitor::clean_names() |>
distinct() |>
mutate(
age = ifelse(is.na(age) | age < 0 | age > 150,
median(age[age > 0 & age < 150], na.rm = TRUE), age),
avg_order_value = ifelse(avg_order_value < 0, NA, avg_order_value)
) |>
drop_na(register_date) |>
filter(monthly_visits >= 0, support_calls >= 0)
cat('After cleaning:', nrow(customers), 'rows\n')
cat(' - Duplicates:', nrow(customers_raw) - nrow(distinct(customers_raw)), 'removed\n')
cat(' - Age Missing/Exception: Processed\n')
cat(' - Abnormal Order Amount: Set to NA\n\n')
# ========== Stage 3: EDA Explore ==========
cat('=== Stage 3: EDA Explore ===\n')
cat('Data Dimensions:', nrow(customers), 'rows x', ncol(customers), 'cols\n')
cat('Churn rate:', round(mean(customers$churn) * 100, 2), '%\n')
churn_by_plan <- customers |>
group_by(plan) |>
summarise(
n = n(),
churn_rate = round(mean(churn) * 100, 2),
avg_age = round(mean(age), 1),
avg_visits = round(mean(monthly_visits), 1)
)
cat('\nChurn Rate by Plan Type:\n')
print(churn_by_plan)
p1 <- ggplot(customers, aes(x = monthly_visits, y = avg_order_value,
color = factor(churn))) +
geom_point(alpha = 0.5) +
geom_smooth(method = 'lm', se = FALSE) +
scale_color_brewer(palette = 'Set1', labels = c('Not lost', 'Loss')) +
labs(title = 'Number of visits vs Average Order Value',
x = 'Monthly Visits', y = 'Average Order Value', color = 'Status') +
theme_minimal()
cat('Generate 2 Key Charts\n\n')
# ========== Stage 4: Descriptive Statistics ==========
cat('=== Stage 4: Descriptive Statistics ===\n')
key_metrics <- customers |>
summarise(
Total Number of Customers = n(),
Number of Lost Customers = sum(churn),
Churn rate = round(mean(churn) * 100, 2),
Average Age = round(mean(age), 1),
Average Monthly Visits = round(mean(monthly_visits), 1),
Average Order Value = round(mean(avg_order_value, na.rm = TRUE), 2),
Average Number of Customer Service Inquiries = round(mean(support_calls), 1)
)
print(key_metrics)
by_city <- customers |>
group_by(city) |>
summarise(
Number of customers = n(),
Churn rate = round(mean(churn) * 100, 2),
Average Order = round(mean(avg_order_value, na.rm = TRUE), 2)
) |>
arrange(desc(Number of customers))
cat('\nBy City:\n')
print(by_city)
cat('\n')
# ========== Stage 5: Modeling and Analysis ==========
cat('=== Stage 5: Modeling and Analysis ===\n')
# 5.1 Logistic Regression: Churn Prediction
churn_model <- glm(churn ~ age + gender + plan + monthly_visits +
avg_order_value + support_calls,
data = customers, family = binomial)
cat('Logistic Regression Model:\n')
summary(churn_model)
cat('\nOdds Ratio Analysis:\n')
or_df <- tidy(churn_model, conf.int = TRUE, exponentiate = TRUE) |>
filter(term != '(Intercept)')
print(or_df |> select(term, estimate, std.error, p.value, conf.low, conf.high))
# 5.3 Linear Regression: Visits Forecast
visit_model <- lm(monthly_visits ~ age + plan + avg_order_value,
data = customers)
cat('\nVisits Forecast Model:\n')
summary(visit_model)
# 5.4 Model Evaluation
library(pROC)
customers$churn_prob <- predict(churn_model, type = 'response')
roc_obj <- roc(customers$churn, customers$churn_prob)
cat('\nChurn Model AUC:', round(auc(roc_obj), 3), '\n\n')
# ========== Stage 6: Visualization and Reporting ==========
cat('=== Stage 6: Visualization and Reporting ===\n')
p2 <- customers |>
group_by(plan, churn) |>
summarise(n = n(), .groups = 'drop') |>
ggplot(aes(x = plan, y = n, fill = factor(churn))) +
geom_col(position = 'fill') +
scale_y_continuous(labels = scales::percent) +
scale_fill_brewer(palette = 'Set1', labels = c('Not lost', 'Loss')) +
labs(title = 'Churn Rates by Plan Type', x = 'Plan', y = 'Ratio', fill = 'Status') +
theme_minimal()
p3 <- customers |>
group_by(plan) |>
summarise(
n = n(),
churn_rate = mean(churn)
) |>
ggplot(aes(x = plan, y = churn_rate, fill = plan)) +
geom_col() +
geom_text(aes(label = paste0(round(churn_rate * 100, 1), '%')),
vjust = -0.5) +
scale_y_continuous(labels = scales::percent,
expand = expansion(mult = c(0, 0.15))) +
labs(title = 'Churn Rates by Plan Type', x = 'Plan', y = 'Churn rate') +
theme_minimal() +
theme(legend.position = 'none')
p4 <- ggplot(customers, aes(x = plan, y = monthly_visits, fill = plan)) +
geom_boxplot() +
labs(title = 'Distribution of Monthly Visits by Plan', x = 'Plan', y = 'Monthly Visits') +
theme_minimal() +
theme(legend.position = 'none')
# 6.2 Save Chart
ggsave('chart_visits_vs_order.png', p1, width = 8, height = 6, dpi = 300)
ggsave('chart_churn_by_plan.png', p2, width = 8, height = 6, dpi = 300)
ggsave('chart_churn_rate.png', p3, width = 8, height = 6, dpi = 300)
ggsave('chart_visits_by_plan.png', p4, width = 8, height = 6, dpi = 300)
# 6.3 Save Model
saveRDS(churn_model, 'churn_model.rds')
saveRDS(visit_model, 'visit_model.rds')
# 6.4 Save the processed data
write_csv(customers, 'customer_clean.csv')
saveRDS(customers, 'customer_clean.rds')
# 6.5 Summary of Business Insights
cat('\n=== Summary of Business Insights ===\n')
cat('1. Overall attrition rate:', round(mean(customers$churn) * 100, 2), '%\n')
cat('2. Customers with >5 support calls churn rate:',
round(mean(customers$churn[customers$support_calls > 5]) * 100, 2), '%\n')
cat('3. Customers with <5 monthly visits churn rate:',
round(mean(customers$churn[customers$monthly_visits < 5]) * 100, 2), '%\n')
cat('4. The Basic Plan has the highest churn rate (',
round(mean(customers$churn[customers$plan == 'Basics']) * 100, 2), '%)\n')
cat('5. Older age and fewer visits -> higher probability of attrition\n')
cat('6. Suggestion: Add customers with >5 support calls to the high-risk list, proactively retain\n')
cat('\n=== All Done ===\n')
cat('Output Files:\n')
cat(' - customer_raw.csv (Raw Data)\n')
cat(' - customer_clean.csv / .rds (Data After Cleaning)\n')
cat(' - chart_*.png (4 charts)\n')
cat(' - churn_model.rds (Churn Prediction Model)\n')
cat(' - visit_model.rds (Visits Forecast Model)\n')
(2) R Markdown レポートテンプレート(簡略版)
完全な Rmd テンプレートの構造(YAML + 6 つのセクション + R コードブロック + 説明文)に従って、新しい customer_report.Rmd ファイルを作成してください:
YAMLメタデータ(ファイルの先頭):タイトル、著者、出力形式(html_document + theme: flatly + toc: true)を定義します。
6つの主要な章:
- プロジェクトの概要 - 簡単な背景説明 + 3つの分析目的
- データの概要 - クリーニング済みのデータの読み込み + Skimrによる要約
- 探索的分析 - 解約率 + プラン別分布 + 散布図
- 統計モデル - 保存済みの churn_model.rds ファイルを読み込み、整理して表示するか、または
- 主な調査結果 - 箇条書き(3~5項目)、または解釈
- ビジネス提言 - 実践可能な提言3件 + 付録一覧
各章は、セクション間の見出しである R コードブロック(```{r}) embedding analysis code, with ## 1. xxx / ## 2. xxx)によって区切られています。
(3) レポートを作成する
# Generate HTML Report
rmarkdown::render('customer_report.Rmd',
output_format = 'html_document',
output_file = 'customer_report.html')
# Generate PDF Report (LaTeX installation required)
rmarkdown::render('customer_report.Rmd',
output_format = 'pdf_document',
output_file = 'customer_report.pdf')
期待される出力:
- 10~15ページ分のHTMLレポート1部(コード、結果、図表、分析を含む)
- PNG形式のグラフ4点
- 2 .rdsモデル
- クリーンなデータを含む CSV ファイル 1 つ
9. Rチュートリアルの完全な学習パス
(1) 5つの段階
graph TB
A[Phase 1 Basics 10 lessons] --> B[Phase 2 Data 7 lessons]
B --> C[Phase 3 Visualization 5 lessons]
C --> D[Phase 4 Statistics 5 lessons]
D --> E[Phase 5 Practical Application 3 lessons]
E --> F[End Able to work independently on projects]
style A fill:#cce5ff
style B fill:#d4edda
style C fill:#f8d7da
style D fill:#e1d4ff
style E fill:#ffe1d4
style F fill:#fff3cd
(2) 30のレッスンの一覧
| フェーズ | クラス | トピック |
|---|---|---|
| 1 基礎 | 01-10 | Rの概要 / 基本的な構文 / データ型 / ベクトル / 演算子 / 制御構造 / 関数 / 行列 / リスト / データフレーム |
| 2 データ | 11-17 | CSV / Excel / JSON / データベース / 文字列 / 正規表現 / リファクタリング |
| 3 可視化 | 18–22 | 基本的なプロット / ggplot2 の入門 / 応用 / テーマ / 地図 |
| 4 統計学 | 23–27 | 記述統計 / 確率分布 / 仮説検定 / 線形回帰 / ロジスティック回帰 |
| 5つの実践演習 | 28–30 | EDA / データクレンジング / 総合レポート |
10. 今後の研究に向けた提言
(1) 高度なRパッケージ
| バッグ | 用途 |
|---|---|
| シャイニー | Webアプリケーション(インタラクティブ・ダッシュボード) |
| 配管工 | REST API(機械学習のデプロイ) |
| tidymodels | 現代の機械学習(caretの代替) |
| torch | ディープラーニング |
| 矢印 | ビッグデータ(Parquetファイル) |
(2) 必須のリソース
| リソース | 説明 |
|---|---|
| 『R for Data Science (第2版)』 | ハドリー氏の公式著書、hadley/r4ds |
| 『Advanced R』(第2版) | 『Advanced R Programming』 |
| ggplot2:洗練されたグラフィックス | ggplot2の原理に関する書籍 |
| R Markdown クックブック | レポートの生成 |
| RStudio チートシート | クイックリファレンスカード |
(3) 実社会でのプロジェクト
- Kaggle (kaggle.com) — 実世界のデータサイエンスコンテスト
- TidyTuesday (tidytues.day) — 毎週配信される無料のデータセット
- 自分のデータ(仕事・趣味・投資)
❓ よくある質問
.Rmd ファイル(YAML メタデータ + Markdown テキスト + R コードブロック)を作成します。rmarkdown::render() HTML/PDF を生成します。RStudio の「Knit」ボタンを使用すれば、ワンクリックでレポートを生成できます。📖 まとめ
- エンドツーエンドのプロジェクトにおける6つの段階:データ → クリーニング → 探索的データ分析(EDA) → 記述 → モデリング → レポート作成
- R Markdown = ドキュメント、コード、結果、図表を統合したレポート作成ツール
saveRDSは単一のオブジェクトを永続化し、write_csvはテーブルを永続化し、ggsaveはチャートを永続化する- RStudioプロジェクト + renv + Git = データサイエンスの三本柱
- 30のレッスンで、Rを用いたデータ分析に必要な作業の80%を網羅しています。残りの20%については、機械学習/深層学習の拡張機能が必要となります。
- 次:tidymodels(機械学習)/Shiny(ダッシュボード)/plumber(API)/tidytext(テキスト)
- 重要な概念:データからインサイトに至るエンドツーエンドのワークフロー=データサイエンティストに求められる基本的なスキル
- チュートリアル完了――これでRを使ったデータ分析プロジェクトを自力で完了できるようになりました
📝 練習問題
卒業プロジェクト課題(エンドツーエンドのデータ分析プロジェクトの完了、Rチュートリアル第30課の最終プロジェクト):
- データの選択:公開データセットを1つ選択してください(推奨:Titanic / Iris / mtcars / mpg / nycflights13)
- プロセス全体:
- 手順 1:データを読み込む(
readrまたはdatasetsを使用) - フェーズ2:クリーニング(欠落・異常・重複・タイプ)
- フェーズ3:EDA(要約+スキム分析+可視化)
- フェーズ4:記述統計(グループ別集計)
- ステップ5:モデリング(lm または glm)
- フェーズ6:レポート(R Markdown HTML)
- 手順 1:データを読み込む(
- 成果物:
analysis.Rメインスクリプト(200行以上)report.RmdR Markdown レポート- 5つ以上のグラフ
-
- ビジネスインサイトの概要(500文字)
- 評価基準:
- コードが動作する(20点)
- プロセス全体(20点)
- 分析の深さ(20点)
- 見栄えの良いグラフ(20点)
- 報告書の読みやすさ(20点) 卒業プロジェクトの完了=Rチュートリアルの完了!
▶ サンプル:第30課のまとめ
# ============================================
# R Tutorial 30 Lesson Study Summary Script
# After running, it outputs the topic for each lesson
# ============================================
lessons <- c(
"01 UnderstandingR", "02 Basic Grammar", "03 Data Types", "04 Vector",
"05 Operators", "06 Control Flow", "07 Function", "08 Matrices and Arrays",
"09 List", "10 Data Frames and Factors",
"11 CSV", "12 Excel", "13 JSON and XML", "14 Database",
"15 String", "16 Regular", "17 Data Reimagined",
"18 Basic Drawing", "19 ggplot2 Getting Started", "20 ggplot2 Advanced",
"21 Theme Customization", "22 Map",
"23 Descriptive Statistics", "24 Probability Distribution", "25 Hypothesis Testing",
"26 Linear Regression", "27 Logistic Regression",
"28 EDA", "29 Data Cleaning", "30 Comprehensive Report"
)
cat("R Tutorial 30 Course List:\n")
for (i in seq_along(lessons)) {
cat(sprintf("%2d. %s\n", i, lessons[i]))
}
期待される出力:
R Tutorial 30 Course List:
1. 01 UnderstandingR
2. 02 Basic Grammar
...
30. 30 Comprehensive Report
12. Rチュートリアルの第30レッスンを修了おめでとうございます
これで、「R Data Science」の30のレッスンを、基本的な構文からエンドツーエンドのプロジェクトに至るまで体系的に修了し、実際のデータ分析タスクに自力で取り組む準備が整いました。次は実践的な演習です。実際のデータを見つけ、実際のプロジェクトに取り組み、ポートフォリオを構築していきましょう。皆さんが優れたデータサイエンティストになることを心より願っています!



