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 避免标签重叠。
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()。
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%,若业务分析需要仍可保留。
本章小结:
isna()/isnull()是缺失值检测的基石,返回布尔矩阵。sum()统计缺失数量,mean()统计缺失比例,两者结合可快速评估数据质量。- 缺失热力图通过颜色分布直观展示缺失模式,是数据探索阶段的高效工具。
- 建议将检测逻辑封装为函数,便于在多个数据集中复用。