缺失值识别:使用 isnull() 与 info() 检测缺失值、缺失值热力图可视化
缺失值是数据清洗中最常见的问题之一。在开始处理缺失值之前,必须系统性地识别缺失值的分布、数量与模式。本节将介绍两种最基础的检测方法——isnull() 与 info(),以及一种直观的可视化手段——缺失值热力图。
1. 缺失值检测方法对比
| 方法 | 返回结果 | 适用场景 | 性能特点 |
|---|---|---|---|
df.info() |
DataFrame 概览(列名、非空计数、数据类型) | 快速了解每列缺失情况 | 一次性输出,适合初步探查 |
df.isnull().sum() |
每列缺失值数量(Series) | 精确统计缺失数量 | 返回数值,便于排序与筛选 |
df.isnull().mean() |
每列缺失值占比(0~1) | 评估缺失严重程度 | 直接得到百分比,方便设定阈值 |
df.isnull().any(axis=1) |
每行是否存在缺失值(布尔值) | 定位包含缺失值的样本 | 适合行级筛选与删除 |
2. 使用 info() 快速概览
info() 是 Pandas 中最直接的缺失值检测入口。它会输出 DataFrame 的列名、非空值数量、数据类型以及内存占用。通过对比“非空计数”与“总行数”,可以快速定位哪些列存在缺失。
import pandas as pd
# 加载示例数据
df = pd.read_csv('house_prices.csv')
# 输出 DataFrame 概览
df.info()
输出示例(部分):
RangeIndex: 1460 entries, 0 to 1459Data columns (total 81 columns):LotFrontage 1201 non-null float64Alley 91 non-null objectMasVnrType 1452 non-null object...dtypes: float64(3), int64(35), object(43)memory usage: 924.0+ KB
从输出中可以立即发现:LotFrontage 有 259 个缺失值(1460 - 1201),Alley 有 1369 个缺失值,MasVnrType 有 8 个缺失值。这种方法适合在数据加载后第一时间执行。
3. 使用 isnull() 精确统计
isnull() 返回一个与原始 DataFrame 形状相同的布尔矩阵,True 表示缺失。配合 sum() 或 mean() 可以快速得到每列的缺失数量或比例。
# 统计每列缺失数量
missing_count = df.isnull().sum()
# 筛选出存在缺失的列
missing_cols = missing_count[missing_count > 0]
# 按缺失数量降序排列
missing_cols_sorted = missing_cols.sort_values(ascending=False)
print(missing_cols_sorted)
实用技巧:将缺失比例与列的数据类型结合分析。数值型列缺失超过 50% 通常建议删除;类别型列缺失可能代表“无此特征”,可单独编码为
'None' 或 'Missing'。
4. 缺失值热力图可视化
热力图可以直观展示缺失值在行与列上的分布模式,帮助发现缺失是否随机、是否集中在某些样本或某些特征上。使用 seaborn.heatmap() 配合 isnull() 即可快速绘制。
import matplotlib.pyplot as plt
import seaborn as sns
# 绘制缺失值热力图
plt.figure(figsize=(12, 8))
sns.heatmap(df.isnull(), cbar=False, cmap='viridis', yticklabels=False)
plt.title('缺失值热力图', fontsize=16)
plt.xlabel('特征列', fontsize=12)
plt.ylabel('样本行', fontsize=12)
plt.tight_layout()
plt.show()
注意:当数据行数较多(超过 1000 行)时,建议设置
yticklabels=False 避免坐标轴标签重叠。如果特征列数超过 50,可考虑只绘制存在缺失的列子集,以提升可读性。
热力图中,黄色/亮色区域表示缺失值,深色区域表示非缺失值。通过观察纵向条纹可以判断哪些列缺失严重;横向条纹可以判断哪些样本包含较多缺失值;如果缺失呈现块状或带状分布,说明缺失可能存在系统性原因。
5. 综合检测流程
在实际项目中,建议按以下步骤系统性地识别缺失值:
- 第一步:调用
df.info()获取全局概览,记录每列非空计数。 - 第二步:使用
df.isnull().sum()精确统计缺失数量,并计算缺失比例。 - 第三步:筛选缺失比例超过阈值的列(如 30%、50%、80%),决定保留或删除。
- 第四步:绘制缺失值热力图,观察缺失分布是否存在规律。
- 第五步:结合业务逻辑判断缺失原因(数据未采集、用户未填写、系统错误等)。
关键指标:
- 缺失数量:
df.isnull().sum() - 缺失比例:
df.isnull().mean() * 100 - 缺失行数:
df.isnull().any(axis=1).sum() - 完整行数:
df.dropna().shape[0]
6. 常见误区与避坑
| 误区 | 正确做法 |
|---|---|
| 只关注缺失数量,忽略缺失比例 | 同时计算缺失比例,结合列重要性判断 |
认为 NaN 是唯一的缺失表示 |
检查 None、''、'NA'、'null' 等占位符 |
热力图设置 yticklabels=True 导致图面拥挤 |
行数超过 500 时关闭 y 轴标签,或只抽样绘制 |
| 忽略缺失值的列间关联 | 使用热力图或 corr() 检查缺失是否同时出现在多列 |
7. 实战案例:房价数据集缺失检测
以 Kaggle 房价数据集为例,演示完整的缺失值识别流程:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 加载数据
df = pd.read_csv('train.csv')
# 第一步:info() 概览
print("=== 数据概览 ===")
df.info()
# 第二步:缺失统计
missing = df.isnull().sum()
missing_pct = (missing / len(df)) * 100
missing_df = pd.DataFrame({'缺失数量': missing, '缺失比例(%)': missing_pct.round(2)})
missing_df = missing_df[missing_df['缺失数量'] > 0].sort_values('缺失比例(%)', ascending=False)
print("\n=== 存在缺失的列 ===")
print(missing_df.head(10))
# 第三步:热力图(只绘制存在缺失的列)
missing_cols = missing_df.index.tolist()
plt.figure(figsize=(14, 6))
sns.heatmap(df[missing_cols].isnull(), cbar=False, cmap='viridis', yticklabels=False)
plt.title('房价数据集缺失值热力图(仅含缺失列)', fontsize=14)
plt.xlabel('特征列', fontsize=11)
plt.ylabel('样本行', fontsize=11)
plt.tight_layout()
plt.show()
输出解读:在房价数据集中,
PoolQC、MiscFeature、Alley 等列的缺失比例超过 90%,这些列通常代表“无此设施”,应编码为 'None' 而非删除。而 LotFrontage 缺失约 18%,属于中等缺失,可考虑用中位数或回归填补。
8. 缺失值检测清单
- ☐ 使用
info()检查每列非空计数 - ☐ 使用
isnull().sum()统计缺失数量 - ☐ 计算缺失比例,设定阈值(如 30%、50%、80%)
- ☐ 绘制缺失值热力图,观察分布模式
- ☐ 检查是否存在
None、''、'NA'等非标准缺失值 - ☐ 记录缺失列的业务含义,为后续处理做准备