R: R 综合数据分析报告:端到端完整项目

最后更新:2026-08-26

这是 R 教程的最后一课——把前面 29 课所有知识串起来,做一个端到端完整项目。从读数据到清洗、EDA、建模、可视化、输出报告,模拟真实数据分析师的一天。

读完这一课你就有能力独立完成完整 R 数据分析项目——数据科学求职面试作品集级别。

1. 你将学到



2. 一个数据分析师一天的故事

(1) 痛点:从数据到报告要 3 天

Alice是数据分析师,接到任务:分析 2024 年客户行为,给manager一份完整报告

传统流程:读 Excel → 清洗 → Excel 透视表 → 画图 → 复制到 PPT → 写分析 → manager 1 周后要看。

(2) R 的解法

R
# 1. 一行 R Markdown 报告
rmarkdown::render('customer_analysis.Rmd')

1 行代码 → 完整 HTML/PDF 报告(含代码、结果、图表、解读)。



3. 端到端项目 6 阶段

100%
graph TB
    A[1. 数据加载] --> B[2. 数据清洗]
    B --> C[3. EDA 探索]
    C --> D[4. 描述统计]
    D --> E[5. 建模分析]
    E --> F[6. 可视化与报告]

    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 脚本

R
# ============================================
# 客户行为分析 - 端到端项目
# 阶段:1. 数据加载 → 6. 报告输出
# ============================================

library(readr)
library(dplyr)
library(tidyr)
library(stringr)
library(lubridate)
library(ggplot2)
library(broom)
library(skimr)

# ========== 阶段 1:数据加载 ==========
cat('=== 阶段 1:数据加载 ===\n')

set.seed(42)
n <- 2000
customers_raw <- tibble(
  customer_id = 1:n,
  age = round(rnorm(n, 35, 12)),
  gender = sample(c('男', '女'), n, replace = TRUE),
  city = sample(c('北京', '上海', '广州', '深圳', '杭州'), 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('基础', '高级', '企业'), 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('已加载', nrow(customers_raw), '行原始数据\n\n')

# ========== 阶段 2:数据清洗 ==========
cat('=== 阶段 2:数据清洗 ===\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('清洗后:', nrow(customers), '行\n')
cat('  - 重复:', nrow(customers_raw) - nrow(distinct(customers_raw)), '行已去\n')
cat('  - 年龄缺失/异常:已处理\n')
cat('  - 订单金额异常:已置 NA\n\n')

# ========== 阶段 3:EDA 探索 ==========
cat('=== 阶段 3:EDA 探索 ===\n')

cat('数据维度:', nrow(customers), '行 x', ncol(customers), '列\n')
cat('流失率:', 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('\n按套餐类型的流失率:\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('未流失', '流失')) +
  labs(title = '访问次数 vs 平均订单金额',
       x = '月访问次数', y = '平均订单金额', color = '状态') +
  theme_minimal()

cat('生成 2 张关键图表\n\n')

# ========== 阶段 4:描述统计 ==========
cat('=== 阶段 4:描述统计 ===\n')

key_metrics <- customers |>
  summarise(
    总客户数 = n(),
    流失客户数 = sum(churn),
    流失率 = round(mean(churn) * 100, 2),
    平均年龄 = round(mean(age), 1),
    平均月访问 = round(mean(monthly_visits), 1),
    平均订单金额 = round(mean(avg_order_value, na.rm = TRUE), 2),
    平均客服次数 = round(mean(support_calls), 1)
  )
print(key_metrics)

by_city <- customers |>
  group_by(city) |>
  summarise(
    客户数 = n(),
    流失率 = round(mean(churn) * 100, 2),
    平均订单 = round(mean(avg_order_value, na.rm = TRUE), 2)
  ) |>
  arrange(desc(客户数))
cat('\n按城市统计:\n')
print(by_city)
cat('\n')

# ========== 阶段 5:建模分析 ==========
cat('=== 阶段 5:建模分析 ===\n')

# 5.1 逻辑回归:流失预测
churn_model <- glm(churn ~ age + gender + plan + monthly_visits +
                     avg_order_value + support_calls,
                   data = customers, family = binomial)
cat('逻辑回归模型:\n')
summary(churn_model)

cat('\nOdds Ratio 解读:\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 线性回归:访问次数预测
visit_model <- lm(monthly_visits ~ age + plan + avg_order_value,
                   data = customers)
cat('\n访问次数预测模型:\n')
summary(visit_model)

# 5.4 模型评估
library(pROC)
customers$churn_prob <- predict(churn_model, type = 'response')
roc_obj <- roc(customers$churn, customers$churn_prob)
cat('\n流失模型 AUC:', round(auc(roc_obj), 3), '\n\n')

# ========== 阶段 6:可视化与报告 ==========
cat('=== 阶段 6:可视化与报告 ===\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('未流失', '流失')) +
  labs(title = '各套餐类型流失占比', x = '套餐', y = '比例', fill = '状态') +
  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 = '各套餐类型流失率', x = '套餐', y = '流失率') +
  theme_minimal() +
  theme(legend.position = 'none')

p4 <- ggplot(customers, aes(x = plan, y = monthly_visits, fill = plan)) +
  geom_boxplot() +
  labs(title = '各套餐月访问次数分布', x = '套餐', y = '月访问次数') +
  theme_minimal() +
  theme(legend.position = 'none')

# 6.2 保存图表
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 保存模型
saveRDS(churn_model, 'churn_model.rds')
saveRDS(visit_model, 'visit_model.rds')

# 6.4 保存处理后的数据
write_csv(customers, 'customer_clean.csv')
saveRDS(customers, 'customer_clean.rds')

# 6.5 业务洞察总结
cat('\n=== 业务洞察总结 ===\n')
cat('1. 整体流失率:', round(mean(customers$churn) * 100, 2), '%\n')
cat('2. 客服次数 > 5 的客户流失率:',
    round(mean(customers$churn[customers$support_calls > 5]) * 100, 2), '%\n')
cat('3. 月访问 < 5 的客户流失率:',
    round(mean(customers$churn[customers$monthly_visits < 5]) * 100, 2), '%\n')
cat('4. 基础套餐流失率最高(',
    round(mean(customers$churn[customers$plan == '基础']) * 100, 2), '%)\n')
cat('5. 年龄越大、访问越少 → 流失概率越高\n')
cat('6. 建议:客服次数 > 5 的客户进入高风险名单,主动挽留\n')

cat('\n=== 全部完成 ===\n')
cat('输出文件:\n')
cat('  - customer_raw.csv(原始数据)\n')
cat('  - customer_clean.csv / .rds(清洗后数据)\n')
cat('  - chart_*.png(4 张图)\n')
cat('  - churn_model.rds(流失预测模型)\n')
cat('  - visit_model.rds(访问预测模型)\n')

(2) R Markdown 报告模板(简化版)

新建 customer_report.Rmd 文件,完整 Rmd 模板结构(YAML + 6 章节 + R 代码块 + 文字解读):

YAML 元数据(文件开头):定义 title / author / output format(html_document + theme: flatly + toc: true)。

6 大章节

  1. 项目概述 - 一段背景介绍 + 3 个分析目标
  2. 数据概览 - 加载清洗后数据 + skimr 摘要
  3. 探索性分析 - 流失率 + 各套餐分布 + 散点图
  4. 统计模型 - 加载已保存的 churn_model.rds + tidy 展示 OR
  5. 关键发现 - bullet 列表,3-5 条 OR 解读
  6. 业务建议 - 3 条 actionable 建议 + 附录文件清单

每个章节用 R 代码块(```{r})嵌入分析代码,章节间用 ## 1. xxx / ## 2. xxx 标题分隔。

💡 提示:完整 Rmd 模板省略(可参考 RStudio 官方 R Markdown 模板生成)。核心是 YAML 元数据 + ```{r} 代码块 + #/## 标题 + 文字解读 4 件套。

(3) 生成报告

R
# 生成 HTML 报告
rmarkdown::render('customer_report.Rmd',
                   output_format = 'html_document',
                   output_file = 'customer_report.html')

# 生成 PDF 报告(需安装 LaTeX)
rmarkdown::render('customer_report.Rmd',
                   output_format = 'pdf_document',
                   output_file = 'customer_report.pdf')

预期输出:



9. R 教程完整学习路径

(1) 5 个阶段

100%
graph TB
    A[Phase 1 基础 10 课] --> B[Phase 2 数据 7 课]
    B --> C[Phase 3 可视化 5 课]
    C --> D[Phase 4 统计 5 课]
    D --> E[Phase 5 实战 3 课]
    E --> F[完结 能独立做项目]

    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 课清单

Phase 主题
1 基础 01-10 认识R / 基础语法 / 数据类型 / 向量 / 运算符 / 控制流 / 函数 / 矩阵 / 列表 / 数据框
2 数据 11-17 CSV / Excel / JSON / 数据库 / 字符串 / 正则 / 重塑
3 可视化 18-22 基础绘图 / ggplot2入门 / 进阶 / 主题 / 地图
4 统计 23-27 描述统计 / 概率分布 / 假设检验 / 线性回归 / 逻辑回归
5 实战 28-30 EDA / 数据清洗 / 综合报告


10. 进一步学习建议

(1) 进阶 R 包

用途
shiny Web 应用(交互式仪表板)
plumber REST API(机器学习部署)
tidymodels 现代机器学习(caret 替代)
torch 深度学习
arrow 大数据(Parquet 文件)

(2) 必读资源

资源 说明
R for Data Science (2e) Hadley 大神官方书,hadley/r4ds
Advanced R (2e) R 高级编程
ggplot2: Elegant Graphics ggplot2 原理书
R Markdown Cookbook 报告生成
RStudio Cheatsheets 速查表

(3) 实战项目


❓ 常见问题

Q R Markdown 怎么用?
A 新建 .Rmd 文件(YAML 元数据 + Markdown 文本 + R 代码块)。rmarkdown::render() 生成 HTML/PDF。RStudio Knit 按钮一键出报告。
Q .rds 和 .RData 区别?
A .rds 保存单个对象(如 1 个 model),.RData 保存多个对象(如整个工作空间)。新代码用 .rds 更规范。
Q 模型怎么部署到生产?
A 3 种方式:① plumber 包 写 REST API ② vetiver 包 标准化部署 ③ 导出为 PMML/Python 调用。
Q 项目怎么管理?
A 用 RStudio Project + renv 包(包管理)+ Git(版本控制)+ here 包(路径管理)。
Q 30 课学完能做什么?
A 能独立完成 80% 的数据分析任务——读数据、清洗、EDA、统计、建模、可视化、报告。剩余 20%(机器学习/深度学习/大数据)需要额外学习。
Q 下一步学什么?
A ① 机器学习(tidymodels) ② 文本挖掘(tidytext) ③ 时间序列(fable) ④ Shiny 仪表板 ⑤ R 高级编程(Advanced R)。选一个方向深入即可。

📖 小节



📝 作业

毕业项目作业(完整端到端数据分析项目,R 教程 30 课结业项目)

  1. 数据选择:选 1 个公开数据集(推荐 Titanic / 鸢尾花 / mtcars / mpg / nycflights13)
  2. 完整流程
    • 阶段 1:读数据(readr 或 datasets)
    • 阶段 2:清洗(缺失/异常/重复/类型)
    • 阶段 3:EDA(summary + skimr + 可视化)
    • 阶段 4:描述统计(按组汇总)
    • 阶段 5:建模(lm 或 glm)
    • 阶段 6:报告(R Markdown HTML)
  3. 交付物
    • analysis.R 主脚本(200+ 行)
    • report.Rmd R Markdown 报告
    • 5+ 张图表
    • 1 段业务洞察总结(500 字)
  4. 评分标准
    • 代码可运行(20 分)
    • 流程完整(20 分)
    • 分析深度(20 分)
    • 图表美观(20 分)
    • 报告可读(20 分) 完成毕业项目 = R 教程结业

▶ 示例:30 课学习总结

R
# ============================================
# R 教程 30 课学习总结脚本
# 运行后输出每课的主题
# ============================================

lessons <- c(
  "01 认识R", "02 基础语法", "03 数据类型", "04 向量",
  "05 运算符", "06 控制流", "07 函数", "08 矩阵与数组",
  "09 列表", "10 数据框与因子",
  "11 CSV", "12 Excel", "13 JSON与XML", "14 数据库",
  "15 字符串", "16 正则", "17 数据重塑",
  "18 基础绘图", "19 ggplot2入门", "20 ggplot2进阶",
  "21 主题美化", "22 地图",
  "23 描述统计", "24 概率分布", "25 假设检验",
  "26 线性回归", "27 逻辑回归",
  "28 EDA", "29 数据清洗", "30 综合报告"
)

cat("R 教程 30 课清单:\n")
for (i in seq_along(lessons)) {
  cat(sprintf("%2d. %s\n", i, lessons[i]))
}
▶ 试一试

预期输出:

TEXT 📖 仅展示
R 教程 30 课清单:
 1. 01 认识R
 2. 02 基础语法
...
30. 30 综合报告

12. 恭喜完成 R 教程 30 课

你已经系统学完了 R 数据科学 30 课——从基础语法到端到端项目,能独立完成真实数据分析任务。接下来就是实战——找真实数据,做真实项目,积累作品集。祝你成为优秀的数据科学家!

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏