缺失值检测:从基础方法到可视化诊断

在数据清洗流程中,缺失值检测是第一步,也是最容易被忽视的一步。很多初学者直接调用 dropna() 或 fillna() 处理数据,却不知道数据缺失的模式、比例和分布会直接影响后续填补策略的选择。本节将系统讲解缺失值检测的四种核心方法,并通过可视化手段直观呈现缺失模式。

2.1 基础检测方法

Pandas 提供了四个最常用的缺失值检测工具,它们各有侧重,组合使用可以快速掌握数据集的缺失全貌。

方法 返回结果 适用场景 典型用法
isnull() 布尔型 DataFrame,缺失为 True 逐元素检查,配合 sum() 统计每列缺失数 df.isnull().sum()
isna() 与 isnull() 完全等价 同 isnull(),按个人习惯选用 df.isna().mean()
info() 打印 DataFrame 摘要,含非空计数和数据类型 快速查看每列缺失情况与数据类型 df.info()
describe() 数值型列的统计描述,含 count(非空数) 结合 count 与总行数推算缺失比例 df.describe()
实战建议:先使用 df.info() 快速扫描所有列的非空计数,再用 df.isnull().sum() 精确获取每列缺失数量,最后用 df.isnull().mean() 计算缺失比例,三步即可完成初步诊断。

代码示例:基础检测组合拳

import pandas as pd
import numpy as np

# 构造示例数据
df = pd.DataFrame({
    '年龄': [25, 30, np.nan, 22, 35],
    '收入': [5000, np.nan, 8000, np.nan, 12000],
    '性别': ['男', '女', '女', np.nan, '男'],
    '城市': ['北京', '上海', '广州', '深圳', np.nan]
})

# 1. 快速概览
print("=== info() 输出 ===")
df.info()

# 2. 精确统计
print("\n=== 每列缺失数量 ===")
print(df.isnull().sum())

# 3. 缺失比例
print("\n=== 每列缺失比例 ===")
print(df.isnull().mean())

# 4. 描述统计中的非空计数
print("\n=== describe() 中的 count ===")
print(df.describe().loc['count'])

2.2 缺失模式的可视化诊断

数值统计只能告诉我们“缺了多少”,但无法回答“缺失是否有规律”。可视化缺失模式可以帮助我们发现:缺失是否随机分布?是否存在列之间的缺失关联?缺失是否集中在某些样本上?

2.2.1 缺失值热力图

热力图通过颜色深浅直观展示每列之间的缺失相关性。当两列同时缺失的频率较高时,热力图中对应的格子颜色会加深,提示可能存在“连锁缺失”现象。

关键解读:热力图对角线上的值恒为 1(自身完全相关),重点关注非对角线上的高亮区域。例如,如果“收入”和“年龄”的缺失相关系数达到 0.8,说明这两个字段的缺失高度同步,可能源于同一条数据采集链路的问题。
import matplotlib.pyplot as plt
import seaborn as sns

# 构造缺失指示矩阵
missing_matrix = df.isnull()

# 计算缺失相关性
missing_corr = missing_matrix.corr()

# 绘制热力图
plt.figure(figsize=(8, 6))
sns.heatmap(missing_corr, annot=True, cmap='RdBu_r', 
            vmin=-1, vmax=1, center=0,
            linewidths=0.5, cbar_kws={'label': '缺失相关系数'})
plt.title('缺失值相关性热力图', fontsize=14)
plt.tight_layout()
plt.show()
缺失值热力图结构示意 年龄 收入 性别 城市 年龄 收入 性别 城市 1.00 0.82 0.15 -0.33 0.82 1.00 0.45 0.12 0.15 0.45 1.00 0.78 -0.33 0.12 0.78 1.00 缺失相关系数 1.0(完全同步) 0.5~0.8(高相关) 0.2~0.5(中等) 0~0.2(弱相关) <0(负相关) 解读要点 • 对角线恒为 1.00,表示自身完全相关 • 非对角线高值(如 0.82)提示两列缺失高度同步,可能源于同一数据源问题 • 负值表示一列缺失时另一列反而完整,可能存在互补缺失模式

2.2.2 缺失值矩阵图

缺失值矩阵图(Missing Matrix)以样本为行、特征为列,用颜色标记每个单元格是否缺失。这种可视化方式可以直观展示:缺失是否集中在某些样本上?缺失是否呈现某种结构(如单调缺失、任意缺失)?

注意:当数据集样本量很大(超过 1000 行)时,缺失值矩阵图会变得密集难以阅读。此时建议随机抽样 200~500 行进行可视化,或者使用 msno.matrix() 的 freq 参数控制显示密度。
import missingno as msno

# 使用 missingno 库绘制缺失值矩阵图
# 白色表示数据存在,黑色表示缺失
msno.matrix(df, figsize=(10, 6), fontsize=12, 
            color=(0.2, 0.4, 0.6), sparkline=True)
plt.title('缺失值矩阵图(白色=缺失,黑色=存在)', fontsize=14)
plt.tight_layout()
plt.show()
缺失值矩阵图结构示意 年龄 收入 性别 城市 完整 缺1 缺2 缺2 完整 缺2 完整 缺2 图例 数据存在 数据缺失 矩阵图解读要点 • 横向观察:某一行白色格子多,说明该样本缺失严重,可考虑删除 • 纵向观察:某一列白色格子多,说明该特征缺失比例高,需重点处理 • 模式识别:白色区域是否呈现带状或块状?这提示缺失可能存在系统性原因

2.3 缺失模式分类与应对策略

通过上述检测方法,我们可以将缺失模式分为三类,每类对应不同的处理策略:

缺失模式 定义 检测方法 推荐策略
完全随机缺失(MCAR) 缺失与数据本身无关,纯属偶然 缺失组与非缺失组在其他特征上无显著差异 可直接删除或简单填补
随机缺失(MAR) 缺失依赖于其他完整特征 缺失热力图中存在高相关对 使用回归/模型填补
非随机缺失(MNAR) 缺失依赖于自身真实值 高收入人群更倾向隐瞒收入数据 需领域知识辅助,谨慎处理
检测流程总结:
1. 使用 info() + isnull().sum() 获取缺失数量与比例
2. 使用缺失值矩阵图观察缺失的样本分布
3. 使用缺失热力图检测列之间的缺失关联
4. 结合领域知识判断缺失模式,选择后续处理策略