4、缺失值检测基础:isnull()与isna()方法、缺失值统计(sum/mean)、缺失值可视化(缺失热力图)

缺失值是数据质量检查中最常见的问题之一。本章将系统讲解如何利用 Pandas 内置方法快速定位、统计和可视化缺失值,为后续的清洗与填充奠定基础。

4.1 缺失值检测核心方法:isnull() 与 isna()

Pandas 提供了两个功能完全等价的方法用于检测缺失值:isnull() 和 isna()。它们返回一个与原始 DataFrame 形状相同的布尔型 DataFrame,其中 True 表示该位置为缺失值(NaN 或 None)。

方法 功能 返回值 典型场景
isnull() 检测缺失值,缺失为 True 布尔型 DataFrame / Series 通用缺失检测,语义明确
isna() 检测缺失值,缺失为 True 布尔型 DataFrame / Series 与 NumPy 的 isnan 命名对齐
notnull() 检测非缺失值,非缺失为 True 布尔型 DataFrame / Series 筛选非空行或列
notna() 检测非缺失值,非缺失为 True 布尔型 DataFrame / Series 与 isna() 配套使用
最佳实践: 推荐统一使用 isna() 和 notna(),因为其命名与 NumPy、Scikit-learn 等科学计算库保持一致,代码可读性更高。
import pandas as pd
import numpy as np

# 创建包含缺失值的示例数据
df = pd.DataFrame({
    '姓名': ['张三', '李四', '王五', '赵六'],
    '年龄': [25, np.nan, 30, 28],
    '薪资': [8000, 9500, np.nan, 11000],
    '部门': ['技术', '市场', '技术', np.nan]
})

# 使用 isna() 检测缺失值
print(df.isna())

# 使用 notna() 检测非缺失值
print(df.notna())

4.2 缺失值统计:sum() 与 mean() 的实战应用

布尔值 True 在数值运算中会被视为 1,False 视为 0。利用这一特性,可以快速计算每列或每行的缺失值数量与比例。

4.2.1 缺失值数量统计(sum)

# 每列缺失值数量
print(df.isna().sum())

# 每行缺失值数量
print(df.isna().sum(axis=1))

# 总缺失值数量
print(df.isna().sum().sum())

4.2.2 缺失值比例统计(mean)

# 每列缺失值比例
print(df.isna().mean())

# 每行缺失值比例
print(df.isna().mean(axis=1))

# 整体缺失比例
print(df.isna().mean().mean())
关键指标解读:
  • 缺失数量(sum): 直观反映数据缺失的绝对规模,适合快速定位问题列。
  • 缺失比例(mean): 用于判断缺失是否严重。通常比例 < 5% 可考虑直接删除;5%-20% 需填充;> 20% 需评估该列是否保留。

4.3 缺失值可视化:缺失热力图

当数据集列数较多时,仅靠数值统计难以直观把握缺失模式。缺失热力图(Missing Heatmap)通过颜色深浅直观展示缺失值的分布规律,帮助快速发现系统性缺失或随机缺失。

import matplotlib.pyplot as plt
import seaborn as sns

# 生成缺失热力图
plt.figure(figsize=(10, 6))
sns.heatmap(df.isna(), cbar=False, cmap='viridis', yticklabels=False)
plt.title('缺失值热力图', fontsize=14)
plt.xlabel('列名')
plt.ylabel('样本索引')
plt.tight_layout()
plt.show()
注意: 热力图使用 df.isna() 生成的布尔矩阵作为输入,True(缺失)显示为亮色,False(非缺失)显示为暗色。如果数据集行数过多,建议关闭 yticklabels 避免标签重叠。
缺失值检测与统计流程 原始 DataFrame isna() / isnull() 检测 布尔矩阵 (True/False) sum() / mean() 缺失数量 / 比例 heatmap() 热力图 缺失模式可视化 核心逻辑:布尔矩阵 → 数值聚合(sum/mean)→ 热力图可视化

4.4 实战案例:综合检测与报告生成

以下代码将上述方法整合为一个完整的缺失值检测报告函数,适用于日常数据质量检查脚本。

def missing_report(df):
    """
    生成缺失值检测报告
    参数:
        df: pandas DataFrame
    返回:
        report_df: 包含缺失数量、比例、数据类型的统计表
    """
    report = pd.DataFrame({
        '缺失数量': df.isna().sum(),
        '缺失比例': df.isna().mean(),
        '数据类型': df.dtypes
    })
    report['缺失等级'] = pd.cut(
        report['缺失比例'],
        bins=[-0.001, 0.05, 0.20, 1.0],
        labels=['低', '中', '高']
    )
    return report.sort_values('缺失比例', ascending=False)

# 使用示例
report = missing_report(df)
print(report)

# 可视化报告
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
sns.heatmap(df.isna(), cbar=False, cmap='viridis', ax=axes[0])
axes[0].set_title('缺失值热力图')
report['缺失数量'].plot(kind='bar', ax=axes[1], color='#e74c3c')
axes[1].set_title('各列缺失数量')
axes[1].set_ylabel('缺失数量')
plt.tight_layout()
plt.show()
进阶技巧: 当数据量较大(行数 > 10000)时,建议先对 df.isna() 进行采样再绘制热力图,避免渲染卡顿。采样方法:df.sample(n=5000).isna()。
缺失比例等级判定标准 低缺失 比例 < 5% 直接删除或简单填充 中缺失 5% ≤ 比例 < 20% 均值/中位数/模型填充 高缺失 比例 ≥ 20% 评估是否保留该列 判定依据 缺失比例 = 该列缺失值数量 / 总行数;等级用于辅助决策清洗策略

4.5 常见问题与避坑指南

  • 空字符串 vs NaN: isna() 不会将空字符串 '' 识别为缺失值,需先使用 df.replace('', np.nan) 转换。
  • None 与 NaN 的差异: Pandas 中 None 在数值列会自动转为 NaN,但在对象列可能保留为 None,isna() 对两者均返回 True。
  • 热力图性能: 当 DataFrame 行数超过 10 万时,建议先对 isna() 结果进行 sample() 抽样,或使用 msno.matrix()(missingno 库)替代。
  • 缺失比例阈值: 20% 的阈值并非绝对,需结合业务场景判断。例如,用户画像中的“收入”字段即使缺失 30%,若业务分析需要仍可保留。
本章小结:
  1. isna() / isnull() 是缺失值检测的基石,返回布尔矩阵。
  2. sum() 统计缺失数量,mean() 统计缺失比例,两者结合可快速评估数据质量。
  3. 缺失热力图通过颜色分布直观展示缺失模式,是数据探索阶段的高效工具。
  4. 建议将检测逻辑封装为函数,便于在多个数据集中复用。