Skip to content

元数据卡

  • 前置知识:第2章(数据清洗)、数学基础 B(概率/统计)
  • 预计时间:45 分钟
  • 核心难度:入门
  • 阅读模式:轻松漫游
  • 完成标志:能对一个 DataFrame 做系统性的 EDA 并生成可视化报告

你的进度

你花了大半天把数据洗干净——缺失值补好了,异常值标记了,格式统一了。

现在你面对一张干干净净的数据表。但你发现一个问题:这张表有 50 列、10 万行,你完全不知道里面有什么。平均温度是多少?哪个列的值分布最广?有没有某些列之间看起来有关联?

光盯着数字是看不出来的。你需要让数据自己说话。

你的任务

数据清洗完了,你面前是一张干净的表格。但 200 列 * 10 万行 —— 你看不过来。你没法逐行理解数据在说什么。EDA 就是你的数据侦察手段:用统计和图表快速建立对数据的直觉——分布、趋势、关系、异常,通通可视化出来。


EDA 的三个核心问题

每一轮 EDA 都在回答三个问题:

  1. 单变量——这列数据长什么样? 分布形状、中心趋势、离散程度、缺失
  2. 双变量——两列之间有什么关系? 相关、对比、变化趋势
  3. 多变量——多列交叉能看到什么模式? 分组对比、维度压缩

你从问题 1 开始,逐步深入到问题 3。不要跳过步骤。


单变量分析

看单列数据的第一步:画出它的分布。

python
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

df = pd.read_csv("missions_clean.csv")

# 数值列——直方图
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
df["duration_minutes"].hist(bins=50, ax=axes[0])
axes[0].set_title("Distribution of Duration")

# 类别列——柱状图
df["mission_type"].value_counts().plot(kind="bar", ax=axes[1])
axes[1].set_title("Mission Types")
plt.tight_layout()
plt.show()

直方图告诉你数据的形状:是正态分布?左边多还是右边多?有没有两个峰(双峰分布,暗示有两种不同的数据混合在一起)?

除此之外,你还需要数值摘要:

python
print(df["duration_minutes"].describe())

关注 countmeanstdmin25%50%(中位数)、75%max。如果均值远大于中位数,数据右偏——少数极大值拉高了均值。

双变量分析

现在你想看两列之间的关系。

python
# 散点图——两列关系
plt.figure(figsize=(6, 6))
plt.scatter(df["duration_minutes"], df["success_rate"], alpha=0.3)
plt.xlabel("Duration (min)")
plt.ylabel("Success Rate")
plt.title("Duration vs Success Rate")
plt.show()

# 相关性矩阵
corr = df[["duration_minutes", "success_rate", "team_size", "resources"]].corr()
print(corr)

散点图上的每个点是一次任务。点的分布模式告诉你:

  • 右上倾斜 → 正相关:时间越长,成功率越高?
  • 左下倾斜 → 负相关:时间越长,成功率越低?
  • 无规律 → 不相关

corr() 输出的是相关系数矩阵,范围 -1 到 1。但它只捕捉线性关系。两个变量可以相关系数接近 0,却有强烈的非线性关系(比如 U 形分布)。所以相关系数矩阵不能替代看图。

多变量分析

两列不够了,你想看"不同类型任务下,团队规模和成功率的关系"。

python
# 分组对比
fig, axes = plt.subplots(1, 2, figsize=(12, 4))

# 箱线图:不同任务类型下的成功率分布
df.boxplot(column="success_rate", by="mission_type", ax=axes[0])
axes[0].set_title("Success Rate by Mission Type")

# 分面散点图:按类型着色的 duration vs success_rate
for mt in df["mission_type"].unique():
    subset = df[df["mission_type"] == mt]
    axes[1].scatter(subset["duration_minutes"], subset["success_rate"],
                    label=mt, alpha=0.3)
axes[1].legend()
axes[1].set_xlabel("Duration")
axes[1].set_ylabel("Success Rate")
axes[1].set_title("By Mission Type")
plt.tight_layout()
plt.show()

箱线图是快速理解分组分布的好工具。它显示中位数(箱中线)、四分位距(箱体)、异常值(箱外的点)。如果两个组的箱体完全不重叠,那它们大概率有显著差异。

EDA 自动化

手动画图适合探索。当你需要一份标准化报告时,用 pandas-profiling(现在叫 ydata-profiling)一键生成。

bash
pip install ydata-profiling
python
from ydata_profiling import ProfileReport

report = ProfileReport(df, title="Data Profiling Report", explorative=True)
report.to_file("eda_report.html")

这个 HTML 报告包含:每列的统计摘要、分布直方图、缺失值矩阵、相关性热力图、异常值标注。你不需要在每个项目里从头画所有图——先跑一份自动报告,然后针对有疑问的列深入探索。

EDA 的节奏

你不需要一次性做完所有分析。标准节奏是:

  1. 跑自动报告 → 快速浏览全局
  2. 从报告中挑出"可疑"的列(分布怪异、缺失多、相关性高)
  3. 对这些列手动画图、做交叉分析
  4. 形成假设 → 记录下来
  5. 进入建模阶段后,回到 EDA 验证模型异常

常见陷阱

  • 只看描述统计,不看图。四个季度数据可以有完全相同的均值、方差,但分布形状完全不同(Anscombe's Quartet)。
  • 相关性当作因果。两列高度相关不代表一列导致另一列。
  • 在数据清洗前做 EDA。脏数据会毁掉你的分布图——一个 -999 的占位符能把直方图拉到离谱的位置。
  • 过度解释。看到一个有趣的模式就认为有重大发现,忘了可能是采样误差。

通关挑战

  • 热身:用 df.describe() 找一个看起来奇怪的列,画出它的直方图验证你的直觉。
  • 挑战:对一个数据集做完整的 EDA——包括单变量分布、双变量散点图、相关性矩阵、分组箱线图——形成 3 条以上关于数据的假设。
  • 观察:跑一份自动 profiling 报告,找出至少一个你手动没发现的数据模式。

验收标准

  • 能对一个数据集做单变量、双变量、多变量分析
  • 能用正确的图回答正确的数据类型(数值→直方图/箱线图,类别→柱状图)
  • 能解释散点图和箱线图的含义
  • 知道相关系数矩阵的局限性

旅人笔记

可视化不是最终的呈现——它是对数据的审讯。你问它问题,它回答,你接着追问。


下一站预告

你已经能通过可视化和统计理解数据了。但当你需要问更复杂的聚合问题时,需要更强的武器——下一章,分析型 SQL。

Built with VitePress | Software Systems Atlas