df.isna().mean()可直接计算各列缺失率,返回0~1的Series,比循环更简洁高效,支持多种数据类型,且内部已做安全处理避免除零错误。

用 isna() + mean() 一行算出各列缺失率
直接对 DataFrame 调用 df.isna().mean() 就能得到每列缺失值占比(0~1 的浮点数),比写循环或 apply(lambda x: x.isna().sum() / len(x)) 更简洁、更快。Pandas 对布尔型 DataFrame 的 mean() 默认按列计算,True 当 1 算,天然适配缺失统计。
常见错误是误用 sum() 后再除以 shape[0],容易因空列或全 NaN 列导致除零警告;而 mean() 内部已做安全处理。
- 结果是
Series,索引为列名,值为缺失比例 - 若要转成百分数字符串,可链式调用
.mul(100).round(2).astype(str) + '%' - 注意:时间类型、category 类型列也支持,但自定义对象列若含不可哈希/不可比较元素,
isna()可能返回False误判
筛选缺失率超阈值的列用 df.isna().mean() > 0.5
想快速找出缺失超过一半的列?直接布尔索引即可:df.columns[df.isna().mean() > 0.5].tolist()。这比先生成完整统计再 query() 或 loc 更轻量,不产生中间 DataFrame。
实际场景中常用于 EDA 预处理:比如删除缺失 >30% 的列,可写成 df = df.drop(columns=df.columns[df.isna().mean() > 0.3])。
- 阈值建议用小数(如
0.3),别用整数百分比(如30)避免逻辑错位 -
df.isna().mean() > 0.3返回布尔 Series,必须用df.columns[...]提取列名,不能直接传给drop() - 若原 DataFrame 有重复列名,
columns索引会失效,需先确认df.columns.is_unique
导出缺失率报告时别漏掉 sort_values() 和 to_frame()
向同事或文档输出缺失情况时,通常需要排序+加表头。直接 df.isna().mean().sort_values(ascending=False).to_frame('missing_ratio') 最省事,生成带列名的单列表格。
容易踩的坑是忘记 sort_values() —— 缺失率高的列可能散落在中间,人工扫一眼容易漏;还有人用 reset_index() 想转成两列,结果多出一列默认索引,其实 to_frame() 已足够。
-
to_frame()的参数是新列名,不是原列名;后续加reset_index()才能把原列名变回普通列 - 若要同时显示非空数和总数,可用
df.isna().sum().to_frame('missing_count').assign(total=len(df)) - 导出 CSV 时注意
missing_ratio是 float,默认保留多位小数,用round(4)控制精度更稳妥
处理大文件时用 read_csv(..., nrows=10000) 先探查
面对上千万行的 CSV,直接 pd.read_csv() 再算缺失率可能内存爆掉。正确做法是先用 nrows 读少量样本,快速评估各列缺失模式——多数情况下样本缺失率与全量高度相关。
特别注意:如果缺失集中在文件尾部(比如日志截断),小样本会严重低估,这时得结合业务判断是否要分块统计(用 chunksize)。
- 推荐起始样本量:1–5 万行,兼顾速度与代表性
-
dtype参数尽量指定,尤其对含混合类型的列(如字符串里夹数字),否则object类型下isna()可能慢 3 倍以上 - 别在样本 DataFrame 上调用
df.info()查内存,它本身会触发全量扫描,改用df.memory_usage(deep=True).sum()
真正麻烦的是缺失模式和业务含义强耦合的情况——比如某列缺失只出现在特定用户分组里,单纯看百分比没意义。这时候得把缺失率和分组字段联合分析,而不是止步于单列统计。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











