4. 缺失值检测:isnull()、sum()、isna() 与可视化
缺失值是数据质量检查中最常见的问题之一。在 Pandas 中,isnull() 和 isna() 是检测缺失值的核心方法,配合 sum() 可以快速统计每列的缺失数量。可视化工具(热力图、条形图)则能直观展示缺失模式,帮助判断缺失是随机分布还是存在系统性偏差。
4.1 核心检测方法对比
| 方法 | 返回值 | 适用场景 | 备注 |
|---|---|---|---|
isnull() |
布尔型 DataFrame | 通用缺失检测 | NaN / None / NaT 均视为缺失 |
isna() |
布尔型 DataFrame | 与 isnull() 完全等价 | 别名,推荐用于语义清晰 |
notna() |
布尔型 DataFrame | 检测非缺失值 | 与 isna() 逻辑相反 |
sum() |
Series(每列缺失计数) | 统计缺失总量 | True 计为 1,False 计为 0 |
最佳实践: 使用
df.isna().sum() 一行代码即可获得全表缺失值概览。若需查看缺失比例,可配合 df.isna().mean() 得到每列缺失率。
4.2 基础代码示例
import pandas as pd
import numpy as np
# 构造含缺失值的示例数据
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五', '赵六', None],
'年龄': [25, None, 30, 22, 28],
'工资': [5000, 6000, None, 5500, 6200],
'入职日期': pd.to_datetime(['2020-01-15', '2021-03-20', None, '2019-07-01', '2022-11-10'])
})
# 1. 检测缺失值(布尔矩阵)
print("缺失值布尔矩阵:")
print(df.isna())
# 2. 统计每列缺失数量
print("\n每列缺失数量:")
print(df.isna().sum())
# 3. 统计缺失比例
print("\n每列缺失比例:")
print(df.isna().mean())
# 4. 查看总缺失数
total_missing = df.isna().sum().sum()
print(f"\n数据表总缺失数:{total_missing}")
4.3 缺失值可视化
可视化能快速揭示缺失模式:缺失是随机散布还是集中在某些列/行?是否存在块状缺失?以下两种图形是数据质量检查的标准工具。
4.3.1 缺失值热力图
热力图以颜色深浅直观显示缺失位置,适合快速定位缺失集中区域。
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('缺失值热力图(黄色=缺失,紫色=非缺失)')
plt.xlabel('列名')
plt.ylabel('行索引')
plt.tight_layout()
plt.show()
4.3.2 缺失值条形图
条形图展示每列缺失数量的排序分布,适合对比不同列的缺失严重程度。
# 绘制缺失值条形图
missing_counts = df.isna().sum()
missing_counts = missing_counts[missing_counts > 0].sort_values(ascending=False)
plt.figure(figsize=(8, 5))
missing_counts.plot(kind='bar', color='#e74c3c', edgecolor='#c0392b')
plt.title('各列缺失值数量分布')
plt.xlabel('列名')
plt.ylabel('缺失数量')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
4.4 缺失模式分析流程
- 初步统计: 使用
df.isna().sum()获取每列缺失数量,df.isna().mean()获取缺失率。 - 可视化探查: 绘制热力图观察缺失分布模式(随机 / 块状 / 列集中)。
- 排序对比: 绘制条形图按缺失数量排序,识别高缺失列。
- 关联分析: 检查缺失是否与其他列存在关联(例如某列缺失时另一列也缺失)。
- 决策: 根据缺失比例和模式选择填充、删除或标记策略。
常见陷阱: 空字符串
'' 和字符串 'NaN' 不会被 isna() 识别为缺失值。需先使用 replace() 或 mask() 将其转换为真正的 NaN。
4.5 进阶:缺失值关联检测
有时缺失并非独立事件。以下代码检测两列缺失是否同时发生:
# 检测两列是否同时缺失
both_missing = df['年龄'].isna() & df['工资'].isna()
print(f"年龄和工资同时缺失的行数:{both_missing.sum()}")
# 缺失关联矩阵(热力图变体)
missing_corr = df.isna().corr()
print("\n缺失值相关系数矩阵:")
print(missing_corr)
关键指标: 缺失相关系数接近 1 表示两列缺失高度同步,可能存在数据采集层面的系统性原因(如同一设备故障导致多个字段缺失)。