R: R EDA 探索性分析

最后更新:2026-08-26

前面 6 课我们学了描述统计 + 概率分布 + 假设检验 + 回归——都是"分析"工具。但数据分析的第一步不是建模,而是EDA(Exploratory Data Analysis)——探索数据"长什么样"。这一课学 R EDA 完整方法论。

读完这一课你就能用 R 完整探索任何数据集:数据形状、分布、异常、缺失、相关——为后续建模铺路。

1. 你将学到



2. 一个陌生数据集的痛点

(1) 痛点:100 列的 CSV 怎么开始?

Bob收到一份 100 列、10000 行的客户数据,manager问:"先分析一下这数据"。他盯着 Excel 5 分钟,不知道从哪开始

(2) R 的解法

R
library(DataExplorer)

# 一行 EDA 报告
create_report(df, output_file = "eda_report.html")

1 行代码 → 完整 EDA HTML 报告(30+ 页图表 + 统计)。



3. EDA 完整流程(5 步)

(1) 5 步法

100%
graph TB
    A[1. 数据形状] --> B[2. 数据类型]
    B --> C[3. 缺失值分析]
    C --> D[4. 分布探索]
    D --> E[5. 关系探索]
    
    A --> A1[dim/str/head]
    B --> B1[summary/skimr]
    C --> C1[md.pattern/naniar]
    D --> D1[直方图/箱线]
    E --> E1[散点/相关矩阵]
    
    style A fill:#fff3cd
    style B fill:#cce5ff
    style C fill:#d4edda
    style D fill:#f8d7da
    style E fill:#e1d4ff

(2) 5 步法速查

步骤 目标 关键函数
1. 形状 数据多大? dim() nrow() ncol() str()
2. 类型 列什么类型? sapply(df, class) summary()
3. 缺失 缺多少? colSums(is.na()) skimr naniar
4. 分布 数值范围? hist() boxplot() geom_density()
5. 关系 列之间相关? pairs() cor() corrplot


4. 步骤 1:数据形状

R
# 准备数据
df <- iris  # 用 iris 演示

# 基本信息
dim(df)         # [1] 150 5  ← 150 行 5 列
nrow(df)        # [1] 150
ncol(df)        # [1] 5
names(df)       # 列名
str(df)         # 结构
# 'data.frame':	150 obs. of  5 variables:
#  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 ...
#  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 ...
#  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 ...
#  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 ...
#  $ Species     : Factor w/ 3 levels "setosa",...

# 数据预览
head(df, 3)    # 前 3 行
tail(df, 3)    # 后 3 行


5. 步骤 2:类型与摘要

(1) 数值列 vs 分类列

R
# 列类型
sapply(df, class)
# Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species
#   "numeric"    "numeric"   "numeric"   "numeric"    "factor"

# 自动识别
library(dplyr)
df |> summarise(across(everything(), class))

(2) summary() 一行摘要

R
summary(iris)
#   Sepal.Length    Sepal.Width     Petal.Length    Petal.Width
#  Min.   :4.30   Min.   :2.00   Min.   :1.00   Min.   :0.1
#  1st Qu.:5.10   1st Qu.:2.80   1st Qu.:1.60   1st Qu.:0.3
#  Median :5.80   Median :3.00   Median :4.35   Median :1.3
#  Mean   :5.84   Mean   :3.05   Mean   :3.76   Mean   :1.2
#  3rd Qu.:6.40   3rd Qu.:3.30   3rd Qu.:5.10   3rd Qu.:1.8
#  Max.   :7.90   Max.   :4.40   Max.   :6.90   Max.   :2.5
#       Species
#  setosa    :50
#  versicolor:50
#  virginica :50

(3) skimr 高级摘要

R
install.packages("skimr")
library(skimr)

skim(iris)
# ── Data Summary ────────────────────────
# Values                           
# Number of rows                   150
# Number of columns                  5
# ── Variable type: factor ──
# Species: 1 unique, 50 each
# ── Variable type: numeric ──
# Sepal.Length: mean=5.84, sd=0.83, p0=4.3, p25=5.1, p50=5.8, p75=6.4, p100=7.9
# ...(每个变量 20+ 指标)


6. 步骤 3:缺失值分析

(1) 缺失值统计

R
# 模拟含缺失的数据
df <- data.frame(
  a = c(1, 2, NA, 4),
  b = c("x", NA, "z", "w"),
  c = c(NA, 2, 3, NA)
)

# 缺失值数量
colSums(is.na(df))
# a b c
# 1 1 2

# 缺失值比例
colMeans(is.na(df)) * 100
# a b c
# 25 25 50

# 整行 NA
sum(!complete.cases(df))  # [1] 3

(2) naniar 高级缺失值可视化

R
install.packages("naniar")
library(naniar)

# 缺失值模式
vis_miss(iris)  # iris 无缺失,会画空图
# 模拟含缺失
df_with_na <- iris
df_with_na[sample(150, 20), 1] <- NA
df_with_na[sample(150, 10), 3] <- NA
vis_miss(df_with_na)

# 缺失相关性
gg_miss_upset(df_with_na)

# 缺失 vs 变量关系
ggplot(df_with_na, aes(x = Sepal.Length, y = Petal.Length)) +
  geom_miss_point()  # 红点是缺失


7. 步骤 4:分布可视化

(1) 单变量分布

R
library(ggplot2)

# 直方图
ggplot(iris, aes(x = Sepal.Length)) +
  geom_histogram(bins = 30, fill = "skyblue", color = "white") +
  labs(title = "Sepal.Length 分布")

# 密度图
ggplot(iris, aes(x = Sepal.Length, fill = Species)) +
  geom_density(alpha = 0.5) +
  labs(title = "按 Species 的 Sepal.Length 分布")

# 箱线图(识别异常值)
ggplot(iris, aes(y = Sepal.Length)) +
  geom_boxplot(fill = "lightblue", outlier.color = "red") +
  labs(title = "Sepal.Length 箱线图")

# 按组分箱线图
ggplot(iris, aes(x = Species, y = Sepal.Length, fill = Species)) +
  geom_boxplot() +
  labs(title = "按 Species 的 Sepal.Length 分布")

(2) 多变量分布

R
# 散点图 + 回归
ggplot(iris, aes(x = Sepal.Length, y = Petal.Length, color = Species)) +
  geom_point(size = 3) +
  geom_smooth(method = "lm", se = FALSE) +
  labs(title = "Sepal vs Petal 长度")

# 成对图(散点图矩阵)
library(GGally)
ggpairs(iris, aes(color = Species))

(3) 相关矩阵

R
# Calculate相关系数
cor_matrix <- cor(iris |> select(-Species))
print(round(cor_matrix, 2))

# 可视化相关矩阵
library(corrplot)
corrplot(cor_matrix, method = "circle", type = "upper")

# ggplot2 版本
library(reshape2)
melted <- melt(cor_matrix)
ggplot(melted, aes(Var1, Var2, fill = value)) +
  geom_tile() +
  scale_fill_gradient2(low = "blue", high = "red", mid = "white",
                       midpoint = 0) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))


8. 步骤 5:异常值检测

(1) IQR 法(最稳健)

R
detect_outliers <- function(x) {
  q1 <- quantile(x, 0.25, na.rm = TRUE)
  q3 <- quantile(x, 0.75, na.rm = TRUE)
  iqr <- q3 - q1
  lower <- q1 - 1.5 * iqr
  upper <- q3 + 1.5 * iqr
  x < lower | x > upper
}

# 应用
iris |>
  mutate(across(where(is.numeric), detect_outliers, .names = "{.col}_out")) |>
  select(ends_with("_out")) |>
  summarise(across(everything(), sum))

# Sepal.Length_out Sepal.Width_out Petal.Length_out  Petal.Width_out
#        0                4               0                0

(2) 3σ 法(仅正态数据)

R
detect_outliers_z <- function(x, threshold = 3) {
  z <- (x - mean(x, na.rm = TRUE)) / sd(x, na.rm = TRUE)
  abs(z) > threshold
}


9. 自动化 EDA

(1) DataExplorer

R
install.packages("DataExplorer")
library(DataExplorer)

# 1. 一行报告
create_report(iris, output_file = "eda_report.html")

# 2. 报告内容
plot_intro(iris)        # 数据介绍
plot_missing(iris)      # 缺失值
plot_histogram(iris)    # 所有数值列直方图
plot_density(iris)      # 密度图
plot_bar(iris)          # 分类列条形图
plot_boxplot(iris)      # 箱线图
plot_scatterplot(iris)  # 散点图矩阵
plot_correlation(iris)  # 相关矩阵

(2) SmartEDA

R
install.packages("SmartEDA")
library(SmartEDA)

ExpReport(iris, op_file = "smarteda_report.html")
ExpNumStat(iris)         # 数值统计
ExpCatStat(iris)         # 分类统计


10. 完整示例:iris + mpg 双数据集 EDA

下面是一个完整工作流示例,把本课所有 EDA 知识串起来。

▶ 示例:iris + mpg 双数据集完整 EDA

R 📖 仅展示
# ============================================
# iris + mpg 双数据集完整 EDA
# 功能:5 步 EDA 完整流程
# ============================================

library(ggplot2)
library(dplyr)
library(skimr)
library(naniar)
library(GGally)

# 1. 步骤 1:数据形状
cat("=== 步骤 1:数据形状 ===\n")
cat("iris:", nrow(iris), "行 ×", ncol(iris), "列\n")
cat("mpg:", nrow(mpg), "行 ×", ncol(mpg), "列\n\n")

# 2. 步骤 2:类型 + 摘要
cat("=== 步骤 2:类型与摘要 ===\n")
cat("iris 列类型:\n")
print(sapply(iris, class))
cat("\nmpg 列类型:\n")
print(sapply(mpg, class))

cat("\niris 摘要:\n")
print(summary(iris))

cat("\nmpg 摘要:\n")
print(summary(mpg |> select(displ, year, cyl, cty, hwy)))

# 3. 步骤 3:缺失值分析
cat("\n=== 步骤 3:缺失值 ===\n")
cat("iris 缺失值:", sum(is.na(iris)), "个\n")
cat("mpg 缺失值:", sum(is.na(mpg)), "个\n\n")

# 模拟含缺失数据
set.seed(42)
iris_na <- iris
iris_na[sample(150, 20), 1] <- NA
iris_na[sample(150, 10), 3] <- NA

vis_miss(iris_na, cluster = TRUE)
gg_miss_upset(iris_na)

# 4. 步骤 4:分布可视化
cat("\n=== 步骤 4:分布可视化 ===\n")

# 4.1 数值变量分布
iris |>
  select(-Species) |>
  pivot_longer(everything(), names_to = "variable", values_to = "value") |>
  ggplot(aes(x = value)) +
  geom_histogram(bins = 20, fill = "skyblue", color = "white") +
  facet_wrap(~ variable, scales = "free") +
  labs(title = "iris 4 个数值变量分布")

# 4.2 按组分
ggplot(iris, aes(x = Species, y = Sepal.Length, fill = Species)) +
  geom_boxplot() +
  labs(title = "按 Species 的 Sepal.Length 箱线图")

# 4.3 散点图矩阵
ggpairs(iris, aes(color = Species))

# 5. 步骤 5:相关矩阵
cat("\n=== 步骤 5:相关矩阵 ===\n")
cor_matrix <- cor(iris |> select(-Species))
print(round(cor_matrix, 2))

library(corrplot)
corrplot(cor_matrix, method = "circle", type = "upper",
         addCoef.col = "black", number.cex = 0.8)

# 6. 异常值检测
cat("\n=== 步骤 6:异常值检测 ===\n")
detect_outliers <- function(x) {
  q1 <- quantile(x, 0.25, na.rm = TRUE)
  q3 <- quantile(x, 0.75, na.rm = TRUE)
  iqr <- q3 - q1
  lower <- q1 - 1.5 * iqr
  upper <- q3 + 1.5 * iqr
  sum(x < lower | x > upper, na.rm = TRUE)
}

iris |>
  summarise(across(where(is.numeric), detect_outliers)) |>
  print()

# 7. 自动化报告
cat("\n=== 步骤 7:自动化报告 ===\n")
library(DataExplorer)
create_report(iris, output_file = "iris_eda_report.html")
cat("iris_eda_report.html 已生成\n")
create_report(mpg, output_file = "mpg_eda_report.html")
cat("mpg_eda_report.html 已生成\n")

# 8. 业务洞察总结
cat("\n=== 业务洞察 ===\n")
cat("1. iris 4 数值变量均无缺失\n")
cat("2. Setosa 物种的 Petal.Length 显著小于其他两个\n")
cat("3. Petal.Length 和 Petal.Width 高度相关(0.96)\n")
cat("4. Sepal.Width 分布近似正态\n")
cat("5. mpg 11 数值变量,38 个车型\n")
逻辑代码 68 行(超过 40 行限制,仅展示)

预期输出:30+ 页 EDA HTML 报告 + 多个统计图表。


❓ 常见问题

Q 什么时候用对数变换?
A 有偏分布(右偏)

📖 小节


📝 作业

  1. 基础题:用 R 内置 mtcars 数据集做完整 EDA:① 形状 ② 摘要 ③ 缺失 ④ 4 个数值变量直方图 ⑤ 相关矩阵。截图保存。

  2. 基础题:模拟 1 个含 20% 缺失值的数据框(1000 行 5 列),用 naniar::vis_miss() 可视化缺失模式,对比 3 种处理策略(删除/均值填补/中位数填补)的效果。

  3. 基础题:用 iris 画 4 个数值变量的相关矩阵(corrplot),找出 2 个最相关的变量对,验证散点图。

  4. 进阶题:用 mpg 数据集做完整 EDA:① 形状 ② 摘要 ③ 按 class 分组的箱线图 ④ 按 class 的散点图矩阵 ⑤ 相关矩阵 ⑥ 自动化报告。截图保存。

  5. 挑战题:构造 1 个含 10000 行 20 列的混合数据集(含数值/分类/缺失/异常值),用 DataExplorer::create_report() 生成完整 EDA 报告(HTML 30+ 页),并基于报告写 1 段业务洞察总结(500 字)。

Web-Tutorial.com

Web-Tutorial 技术团队

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

100%

🙏 帮我们做得更好

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

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