缺失值处理(上):缺失值识别、统计与可视化
各位好,欢迎来到第三章。
上一章我们聊了数据清洗的准备工作,包括数据类型转换和重复值处理。今天咱们进入一个更核心的话题——缺失值。
说实话,我做了这么多年数据清洗,遇到最多的坑就是缺失值。你想想看,一个数据集里,如果某个字段空了一大片,你直接拿去做分析,结果基本就是废的。所以,处理缺失值之前,咱们得先搞清楚三件事:哪些地方有缺失?缺了多少?缺失的分布有没有规律?
3.1 缺失值识别:找到那些「空」
缺失值在Python里通常表现为NaN(Not a Number),或者None。但实际项目中,我见过更离谱的——有人把缺失值填成"NULL"、"N/A"、"未知",甚至直接填个0。嗯,这些都属于「伪缺失」,咱们后面会专门讲怎么处理。
先看最标准的识别方法:
import pandas as pd
import numpy as np
# 创建一个带缺失值的示例数据
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五', '赵六'],
'年龄': [25, np.nan, 30, 28],
'收入': [8000, 12000, np.nan, 9500],
'城市': ['北京', '上海', '广州', np.nan]
})
# 识别缺失值
print(df.isnull())
输出结果会是一个布尔矩阵:True表示缺失,False表示正常。我个人习惯用isnull(),当然你也可以用isna(),效果完全一样。
df[df.isnull().any(axis=1)]。这个我在项目里经常用来快速定位「问题行」。
3.2 缺失值统计:到底缺了多少?
识别出缺失值之后,下一步就是统计。说白了,你得知道每个字段缺了多少,占比多少,才能决定下一步怎么处理。
我常用的统计方法就两个:
# 方法1:统计每列缺失数量
print(df.isnull().sum())
# 方法2:统计每列缺失比例
print(df.isnull().mean())
输出结果:
| 字段 | 缺失数量 | 缺失比例 |
|---|---|---|
| 姓名 | 0 | 0% |
| 年龄 | 1 | 25% |
| 收入 | 1 | 25% |
| 城市 | 1 | 25% |
看到这个表格,你可能会想:「才25%的缺失,问题不大吧?」
别急。我在项目中遇到过这样的情况:某个字段缺失比例只有5%,但偏偏这5%的数据集中在某个特定时间段或特定用户群体里。这种「非随机缺失」才是最要命的。所以,光看比例还不够,还得看分布。
3.3 缺失值可视化:热力图
统计数字只能告诉你「缺了多少」,但热力图能告诉你「缺在哪里」。我个人非常喜欢用热力图来快速扫描整个数据集的缺失模式。
Python里最方便的工具是seaborn的heatmap:
import seaborn as sns
import matplotlib.pyplot as plt
# 绘制缺失值热力图
plt.figure(figsize=(10, 6))
sns.heatmap(df.isnull(), cbar=False, cmap='viridis')
plt.title('缺失值热力图')
plt.show()
这张图里,黄色表示有数据,紫色表示缺失。一眼扫过去,你就能看到:
- 哪些字段缺失严重(紫色区域大)
- 缺失值是否集中在某些行(比如某几行全是紫色)
- 不同字段的缺失是否有相关性(比如「年龄」和「收入」同时缺失)
你想想看,如果「年龄」和「收入」同时缺失的行特别多,那说明什么?很可能这些用户是同一批注册的,或者来自同一个数据源。这种模式光靠数字统计是看不出来的。
3.4 知识体系:缺失值处理的完整流程
为了让你对整个流程有个全局认识,我画了一张图。这张图涵盖了从识别到处理的完整链路,咱们这一章只讲前三个步骤,后面几章会继续深入。
这张图里,黄色标注的部分就是咱们这一章要讲的内容。后面的步骤,比如删除、填充、插值,咱们会在下一章详细展开。
3.5 实战小贴士
最后,分享几个我在实际项目中总结的经验:
- 先看整体,再看局部。 先用
isnull().sum()看全局,再用热力图看局部模式。 - 别只看比例,要看绝对值。 100万条数据里缺失1%就是1万条,这个量级不能随便删。
- 记录缺失模式。 我习惯在清洗文档里记一笔:「字段A缺失集中在某时间段,疑似系统bug」。这样后续分析时心里有数。
df.info() 和 df.isnull().sum()。这两个命令能让你在30秒内了解数据的基本健康状况。嗯,真的,30秒就够了。
好了,这一章就到这里。缺失值的识别、统计和可视化,是后续所有处理的基础。你把这些搞扎实了,后面处理起来就顺手多了。
公众号:蓝海数据掘金营,微信 deep3321