元数据卡
- 前置知识:第2章(数据清洗)、数学基础 B(概率/统计)
- 预计时间:45 分钟
- 核心难度:入门
- 阅读模式:轻松漫游
- 完成标志:能对一个 DataFrame 做系统性的 EDA 并生成可视化报告
你的进度
你花了大半天把数据洗干净——缺失值补好了,异常值标记了,格式统一了。
现在你面对一张干干净净的数据表。但你发现一个问题:这张表有 50 列、10 万行,你完全不知道里面有什么。平均温度是多少?哪个列的值分布最广?有没有某些列之间看起来有关联?
光盯着数字是看不出来的。你需要让数据自己说话。
你的任务
数据清洗完了,你面前是一张干净的表格。但 200 列 * 10 万行 —— 你看不过来。你没法逐行理解数据在说什么。EDA 就是你的数据侦察手段:用统计和图表快速建立对数据的直觉——分布、趋势、关系、异常,通通可视化出来。
EDA 的三个核心问题
每一轮 EDA 都在回答三个问题:
- 单变量——这列数据长什么样? 分布形状、中心趋势、离散程度、缺失
- 双变量——两列之间有什么关系? 相关、对比、变化趋势
- 多变量——多列交叉能看到什么模式? 分组对比、维度压缩
你从问题 1 开始,逐步深入到问题 3。不要跳过步骤。
单变量分析
看单列数据的第一步:画出它的分布。
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()直方图告诉你数据的形状:是正态分布?左边多还是右边多?有没有两个峰(双峰分布,暗示有两种不同的数据混合在一起)?
除此之外,你还需要数值摘要:
print(df["duration_minutes"].describe())关注 count、mean、std、min、25%、50%(中位数)、75%、max。如果均值远大于中位数,数据右偏——少数极大值拉高了均值。
双变量分析
现在你想看两列之间的关系。
# 散点图——两列关系
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 形分布)。所以相关系数矩阵不能替代看图。
多变量分析
两列不够了,你想看"不同类型任务下,团队规模和成功率的关系"。
# 分组对比
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)一键生成。
pip install ydata-profilingfrom ydata_profiling import ProfileReport
report = ProfileReport(df, title="Data Profiling Report", explorative=True)
report.to_file("eda_report.html")这个 HTML 报告包含:每列的统计摘要、分布直方图、缺失值矩阵、相关性热力图、异常值标注。你不需要在每个项目里从头画所有图——先跑一份自动报告,然后针对有疑问的列深入探索。
EDA 的节奏
你不需要一次性做完所有分析。标准节奏是:
- 跑自动报告 → 快速浏览全局
- 从报告中挑出"可疑"的列(分布怪异、缺失多、相关性高)
- 对这些列手动画图、做交叉分析
- 形成假设 → 记录下来
- 进入建模阶段后,回到 EDA 验证模型异常
常见陷阱
- 只看描述统计,不看图。四个季度数据可以有完全相同的均值、方差,但分布形状完全不同(Anscombe's Quartet)。
- 相关性当作因果。两列高度相关不代表一列导致另一列。
- 在数据清洗前做 EDA。脏数据会毁掉你的分布图——一个 -999 的占位符能把直方图拉到离谱的位置。
- 过度解释。看到一个有趣的模式就认为有重大发现,忘了可能是采样误差。
通关挑战
- 热身:用
df.describe()找一个看起来奇怪的列,画出它的直方图验证你的直觉。 - 挑战:对一个数据集做完整的 EDA——包括单变量分布、双变量散点图、相关性矩阵、分组箱线图——形成 3 条以上关于数据的假设。
- 观察:跑一份自动 profiling 报告,找出至少一个你手动没发现的数据模式。
验收标准
- 能对一个数据集做单变量、双变量、多变量分析
- 能用正确的图回答正确的数据类型(数值→直方图/箱线图,类别→柱状图)
- 能解释散点图和箱线图的含义
- 知道相关系数矩阵的局限性
旅人笔记
可视化不是最终的呈现——它是对数据的审讯。你问它问题,它回答,你接着追问。
下一站预告
你已经能通过可视化和统计理解数据了。但当你需要问更复杂的聚合问题时,需要更强的武器——下一章,分析型 SQL。