3. 缺失值可视化:使用 missingno 库快速洞察缺失模式

在特征工程中,仅通过 df.isnull().sum() 查看缺失数量远远不够。缺失值的分布位置、出现规律以及变量间的缺失关联,往往隐藏着数据采集异常或系统性偏差。Python 的 missingno 库专为缺失值可视化设计,提供三种核心图表:缺失值矩阵、条形图、热力图,帮助你在几秒内掌握全局缺失结构。

3.1 安装与快速入门

missingno 基于 matplotlib,安装后即可与 pandas DataFrame 无缝配合:

# 安装
pip install missingno

# 导入
import missingno as msno
import pandas as pd
import numpy as np

# 构造示例数据(含缺失)
np.random.seed(42)
df = pd.DataFrame({
    'age': np.random.randint(20, 60, 100).astype(float),
    'income': np.random.normal(50000, 15000, 100).astype(float),
    'education_yrs': np.random.randint(8, 20, 100).astype(float),
    'credit_score': np.random.randint(300, 850, 100).astype(float),
    'loan_amount': np.random.normal(20000, 8000, 100).astype(float)
})
# 随机引入缺失
for col in df.columns:
    mask = np.random.random(100) < 0.15
    df.loc[mask, col] = np.nan

3.2 缺失值矩阵(Matrix)—— 定位缺失“位置”

msno.matrix(df) 将 DataFrame 绘制为一个二维栅格:行 = 样本,列 = 特征。白色单元格表示缺失,黑色表示存在。右侧的 sparkline 显示每行完整度。

核心洞察:如果白色单元格在矩阵中呈现水平条带,说明某些样本存在整行缺失;如果呈现垂直条带,说明某个特征在连续样本区间内集体缺失——这往往是传感器故障或问卷跳转逻辑导致的系统性缺失。
# 绘制缺失值矩阵
msno.matrix(df, figsize=(10, 5), fontsize=12, sparkline=True)
# 默认会显示 matplotlib 图表,在 Jupyter 中直接输出
缺失值矩阵结构示意 样本↓ age income edu_yrs credit loan 存在值 缺失值 🔍 矩阵解读 • 白色垂直条带 → 特征 在某区间集体缺失 • 白色水平条带 → 样本 整行缺失

3.3 缺失值条形图(Bar)—— 量化缺失比例

msno.bar(df) 为每个特征绘制一个条形,高度表示非缺失样本数。右侧的弹性坐标轴自动缩放,让你一眼看出哪个特征缺失最严重。

# 绘制缺失值条形图
msno.bar(df, figsize=(10, 4), fontsize=12, color='#3498db')
特征 非缺失数 缺失数 缺失率 可视化判断
age 87 13 13% 轻度缺失,可均值插补
income 82 18 18% 中度缺失,需考虑模型插补
education_yrs 85 15 15% 轻度缺失
credit_score 79 21 21% 中度偏高,注意是否随机
loan_amount 90 10 10% 轻度缺失
💡 使用建议:条形图适合快速对比各特征的缺失严重程度。如果某个特征缺失率超过 50%,应优先评估该特征是否还有保留价值,而非盲目插补。

3.4 缺失值热力图(Heatmap)—— 发现缺失关联

msno.heatmap(df) 计算特征之间缺失模式的相关性(范围 -1 到 1)。正值表示两个特征倾向于同时缺失或同时存在;负值表示一个特征缺失时,另一个特征倾向于存在。

# 绘制缺失值热力图
msno.heatmap(df, figsize=(8, 6), fontsize=12, cmap='RdBu')
缺失值热力图 — 缺失关联矩阵 age income edu_yrs credit loan age income edu_yrs credit loan 1.00 0.12 -0.08 0.15 -0.05 0.12 1.00 0.18 -0.10 0.09 -0.08 0.18 1.00 0.22 -0.03 0.15 -0.10 0.22 1.00 0.14 -0.05 0.09 -0.03 0.14 1.00 缺失相关性 强正相关 (≈1.0) 弱正相关 (0.1~0.3) 弱负相关 (-0.1~0) 负相关 (<-0.05) 🔍 热力图解读 • 正相关 → 两特征同时缺失 • 负相关 → 此缺彼存 • 绝对值 > 0.5 需重点关注
⚠️ 重要提醒:热力图的相关性是基于缺失二元掩码(0=存在,1=缺失)计算的,并非原始数值的相关性。高正相关意味着两个特征往往同时缺失,这提示它们可能来自同一数据源或同一采集环节——插补时应考虑联合建模,而非单独处理。

3.5 三种图表对比与选择策略

图表类型 函数 最佳用途 适用场景
缺失值矩阵 msno.matrix() 发现缺失的空间分布与条带模式 样本量 < 1000 时最清晰;大样本可抽样后绘制
缺失值条形图 msno.bar() 快速对比各特征的缺失数量/比例 任意规模数据集,作为缺失统计的直观补充
缺失值热力图 msno.heatmap() 检测特征间缺失的关联性 特征数 > 3 时;特征数 < 20 效果最佳

3.6 实战流程:从可视化到插补决策

  1. 第一步:绘制矩阵,检查是否存在系统性缺失条带。如果发现连续样本区间内某特征全白,优先排查数据采集日志。
  2. 第二步:绘制条形图,标记缺失率 > 20% 的特征,列入重点插补名单。
  3. 第三步:绘制热力图,找出缺失相关性 > 0.5 的特征对。这些特征应使用多元插补(如 MICE)而非单变量均值填充。
  4. 第四步:综合决策,根据缺失模式选择插补策略(后续章节详解)。
# 完整可视化流程示例
import missingno as msno
import matplotlib.pyplot as plt

fig, axes = plt.subplots(1, 3, figsize=(18, 5))

# 矩阵
msno.matrix(df, ax=axes[0], fontsize=10, sparkline=True)
axes[0].set_title('缺失值矩阵', fontsize=13, fontweight='bold')

# 条形图
msno.bar(df, ax=axes[1], fontsize=10, color='#3498db')
axes[1].set_title('缺失值条形图', fontsize=13, fontweight='bold')

# 热力图
msno.heatmap(df, ax=axes[2], fontsize=10, cmap='RdBu')
axes[2].set_title('缺失值热力图', fontsize=13, fontweight='bold')

plt.tight_layout()
plt.show()
📌 核心结论:缺失值可视化不是装饰,而是特征工程中诊断缺失机制的关键步骤。矩阵揭示“哪里缺”,条形图揭示“缺多少”,热力图揭示“谁和谁一起缺”。三者结合,才能为后续插补方法的选择提供可靠依据——避免盲目使用均值填充破坏变量间的真实结构。