NaN和空字符串不是一回事:NaN是数值型缺失标记,空字符串是合法字符串;pandas默认仅将空白单元格或NULL/NA转为NaN,而''、'NULL'等需手动指定为缺失值。

缺失值识别:先搞清NaN和空字符串是不是一回事
很多人一上来就用 df.dropna(),结果发现删不干净——因为 CSV 里可能混着空字符串 ''、字符串 'NULL'、甚至带空格的 ' ',这些都不是 Pandas 默认识别的 NaN。Pandas 只在读取时把空白字段(不含引号的空单元格)或明确标记为 NULL/NA 的内容转成 np.nan,其余全当字符串处理。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用
df.isna().sum()查看哪些列真有NaN;再用df.eq('').sum()或df.applymap(lambda x: isinstance(x, str) and x.strip() == '').sum()检查空字符串 - 读取时主动指定缺失值标识:
pd.read_csv('data.csv', na_values=['NULL', 'N/A', '', ' ']) - 对已加载的数据,可统一清理:
df = df.replace(r'^\s*$', np.nan, regex=True)(注意正则要开regex=True)
fillna() 填什么:别无脑填 0 或均值
填错值比留空更危险。比如用 0 填年龄字段,会扭曲统计分布;用均值填时间序列中的缺失,可能掩盖趋势断点。填法必须匹配字段语义和后续用途。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 数值型字段优先考虑前向/后向填充:
df['price'].fillna(method='ffill')(适合时序或有序数据) - 分类字段用众数:
df['category'].fillna(df['category'].mode()[0])(注意mode()返回 Series,要取第一个) - 连续数值字段若缺失少,可用中位数(比均值抗异常值):
df['income'].fillna(df['income'].median()) - 避免全局填:
df.fillna(0)会强制把字符串列也变成0,报TypeError
dropna() 删多少:按行删还是按列删?阈值怎么设
dropna() 默认删掉**任意列含 NaN 的整行**,但实际中常需要更精细控制。比如某列缺失率 95%,删行意义不大;而某关键列只要缺一个,整条记录就得剔除。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 删行时设最低非空列数:
df.dropna(thresh=5)表示每行至少 5 个非空值才保留 - 只针对特定列判断:
df.dropna(subset=['email', 'user_id']),确保核心字段不为空 - 删列要谨慎:
df.dropna(axis=1, how='all')只删全空列;how='any'会误删含部分缺失的有用列 - 删除前务必检查比例:
df.shape[0] - df.dropna().shape[0]看丢了多少行,超 10% 就该回头检查看是否误标了缺失值
写回 CSV 前:确认 NaN 是否被正确导出
直接 df.to_csv('clean.csv') 会把 NaN 写成空字段,但下游系统(比如 Excel 或数据库导入工具)可能不认这种空,或把它当字符串 'nan' 处理。导出行为必须和下游约定一致。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 想保留缺失语义,显式写出空字符串:
df.to_csv('clean.csv', na_rep='') - 想让 Excel 显示为
#N/A,用:df.to_csv('clean.csv', na_rep='#N/A') - 若下游是数据库,通常要求 NULL,此时应确保字段类型支持 null(如用
pd.Int64Dtype()替代int64),否则to_csv会自动转成 float 并写nan - 导出后务必用文本编辑器打开 CSV,确认缺失位置确实是空字段,而不是意外写入了
nan字符串
清洗不是一步到位的动作,而是反复验证的过程:改完一行代码,就要立刻用 df.info() 和抽样 df.head() 看效果。最容易被忽略的是——原始 CSV 编码问题(比如 GBK 乱码导致字段识别失败),它会让所有清洗逻辑从第一步就失效。


















