8.1 探索性数据分析完整案例 EDA 的图形化四步流程:结构排查(行列、类型、缺失)→ 单变量体检(分布、偏态、离群)→ 关系初筛(相关、散点)→ 组间深挖(分面比较、辛普森复查)。每一步都在为后面的建模排除一类风险。 第 8 章开张。本节用 titanic 数据从零走完一遍 EDA,每张图都标注它排除的风险与产出的发现——这才是"拆解台"格式在实战里的样子。 第一步:结构排查 第二步:单变量体检 第三步:关系初筛 第四步:组间深挖与辛普森复查 三等舱男性在各年龄段都垫底——效应方向没有翻转,辛普森风险解除 排错与变式 这套流程最常见的翻车在第三步:survived 这类 0/1 结果列进了相关矩阵,它与 pclass
EDA 的图形化四步流程:结构排查(行列、类型、缺失)→ 单变量体检(分布、偏态、离群)→ 关系初筛(相关、散点)→ 组间深挖(分面比较、辛普森复查)。每一步都在为后面的建模排除一类风险。
第 8 章开张。本节用 titanic 数据从零走完一遍 EDA,每张图都标注它排除的风险与产出的发现——这才是"拆解台"格式在实战里的样子。
import seaborn as sns import matplotlib.pyplot as plt import pandas as pd titanic = sns.load_dataset('titanic') print(titanic.shape) # 输出:(891, 15) # 缺失热图:一图看清缺口的分布模式 ax = sns.heatmap(titanic.isna(), cbar=False, yticklabels=False, cmap='viridis') ax.set_xlabel('列') ax.set_title('缺失值分布:黄线即缺失') # 输出说明:age 列零星缺失约两成,deck 列大面积缺失超七成, # embark_town 少量缺失——deck 基本不可用作特征,age 要考虑填补
# 类型清单:object 与 category 列是后续组间比较的维度候选 print(titanic.dtypes) # 输出说明:survived 与 pclass 是 int64 但语义是类别—— # 第 1.3 节的教训:不转 category,hue 映射会走连续刻度
titanic['pclass'] = titanic['pclass'].astype('category') fig, axes = plt.subplots(1, 3, figsize=(13, 3.5)) sns.histplot(data=titanic, x='age', binwidth=5, ax=axes[0]) axes[0].set_title('年龄') sns.countplot(data=titanic, x='pclass', ax=axes[1]) axes[1].set_title('舱位') sns.histplot(data=titanic, x='fare', binwidth=15, ax=axes[2]) axes[2].set_title('票价(对数感)') plt.show() # 输出说明:年龄近似单峰略右偏、儿童有一个小鼓包; # 三等舱人数最多;票价极度右偏—— # 右偏的金额列在第 6.3 节的检查单里要考虑对数轴
num_cols = titanic.select_dtypes('number').columns corr = titanic[num_cols].corr() ax = sns.heatmap(corr, annot=True, fmt='.2f', cmap='RdBu_r', vmin=-1, vmax=1, center=0) # 输出说明:数值列间的相关都不高——本数据的主要信号在类别列里, # 相关热图的价值恰恰是排除"数值共线"这条岔路
g = sns.catplot(data=titanic, x='pclass', y='survived', hue='sex', kind='point', dodge=True, height=4.5) g.set_axis_labels('舱位', '生存率') # 输出说明:第 4.3 节已拆过的主图——性别效应远大于舱位效应, # 两条线不交叉说明交互弱,主效应模型即可起步 # 辛普森复查:把年龄档位加进来 titanic['age_band'] = pd.cut(titanic['age'], [0, 12, 30, 50, 100], labels=['儿童', '青年', '中年', '老年']) g = sns.catplot(data=titanic, x='age_band', y='survived', hue='sex', col='pclass', kind='point', dodge=True, height=3.2) g.set_titles('{col_var} {col_name}') # 输出说明:拆年龄档后,头等舱女性的高生存率在各年龄段都稳定; # 三等舱男性在各年龄段都垫底——效应方向没有翻转,辛普森风险解除

这套流程最常见的翻车在第三步:survived 这类 0/1 结果列进了相关矩阵,它与 pclass 的系数看着不小,但二值变量的相关系数天然压幅,绝对值只能当方向参考、不能当强度证据——类别型结果变量的关系判断要回到第四步,用 pointplot 的生存率直接读数,让统计口径与视觉口径对齐。另一个高发坑是第四步发现了小组样本极少(比如 Friday 只有十九桌)却继续画误差棒比较:误差棒诚实地变宽了,但下一步若直接断言周五小费率显著偏低就越界了——正确动作是合并相邻小组,或改用 count 加均值的双联图把样本量摆在明面上,而不是删掉小组当没看见。
变式:整份数据全是类别列、没有一个数值列时(问卷数据常这样),第三步的相关热图换成 crosstab 列联表加 heatmap 的版本,数值标注写列占比,其余三步原样执行——流程骨架比具体函数更值得迁移。
EDA 的产出不是图,是文字结论:deck 缺失过半弃用;age 缺失两成、中位数填补并加缺失指示列;fare 极右偏、建模前取对数;主要信号在 sex 与 pclass 的主效应,交互弱;embark_town 与 pclass 相关,警惕代理效应。变式:同一流程套 penguins 时,第二步就会在体重分布里发现物种混合的双峰——四步流程不变,发现清单完全不同,这正是"流程可复用、结论不可预设"的意思。
⚠️ 常见坑:EDA 最常见的失效是跳过第一步直接画相关性——缺失模式本身往往就是信号(age 缺失与生还相关),补了再画反而抹掉证据。
本节要点回顾
- 四步流程:结构、单变量、关系、组间,每步排除一类建模风险;
- 缺失热图先行:缺口的分布模式与机制值得单独一条结论;
- count 摸底是组间比较的资格证:样本悬殊的组结论降级;
- 辛普森复查:主效应显著时,务必拆一层分面确认方向不翻转;
- 交付物是发现清单:图是过程,文字结论才是 EDA 的产品。
下一节把 EDA 的发现喂给模型,看结果如何诚实地画出来。