结论:df.dropna()默认how='any',但常因未识别字符串型缺失值、未赋值/设inplace=True、误用subset格式或忽略inf处理导致失效;应先用isna().sum()验证,再结合subset、thresh或replace统一缺失值。

直接说结论:用 df.dropna() 最快,但默认只删全为 NaN 的行;要删「任一列含缺失值」的行,必须加 how='any' —— 这是新手最常漏掉的参数。
为什么 dropna() 默认不删你想要的行
因为它的默认行为是 how='any'?错。实际默认是 how='any' 吗?再看文档:不对,dropna() 默认是 how='any'?等等——查证后确认:dropna() 默认确实是 how='any',但问题常出在 subset 和 inplace 上。
更常见的误判来自两点:
- 你以为某列有
NaN,其实它是字符串'nan'或空字符串'',dropna()完全不识别这些 - 你调用了
df.dropna()却没赋值或没设inplace=True,原df一点没变
验证是否真有 NaN:用 df.isna().sum() 看每列缺失数量,别靠肉眼扫。
立即学习“Python免费学习笔记(深入)”;
按需删行:how 和 subset 怎么配着用
删行逻辑取决于你想保守还是激进:
-
how='any'(默认):只要指定列中**任意一个**是NaN,整行就删 -
how='all':只有当指定列**全部都是**NaN,才删该行 -
subset=['col_a', 'col_b']:只检查这两列,其余列哪怕全是NaN也不影响判断
例如:只想剔除 'age' 或 'income' 至少一个为空的用户记录:
df_clean = df.dropna(subset=['age', 'income'], how='any')
注意:subset 必须是列名列表,写成字符串 'age,income' 会报 KeyError。
删完发现数据量暴减?先检查缺失类型和阈值
突然只剩几行,大概率不是函数错了,而是数据里混了非标准缺失值:
- 用
df.replace({'': np.nan, 'N/A': np.nan, 'NULL': np.nan}, inplace=True)统一转义 - 用
df.select_dtypes(include=['object']).apply(lambda x: x.str.strip()).replace('', np.nan)清理空格型空值 - 如果只想保留「至少有 N 列非空」的行,改用
thresh参数:df.dropna(thresh=3)表示每行至少 3 个非空值才留下
thresh 比 how 更灵活,尤其适合宽表(列多、允许部分字段缺失)场景。
inplace=True 不是万能解,链式操作时尤其危险
写 df.dropna(inplace=True) 看似省事,但一旦嵌套在管道里就失效:
df.pipe(clean_func).dropna(inplace=True) # ❌ 无效!pipe 返回新对象,inplace 对原 df 无影响
正确做法是显式赋值或用 assign:
df = df.pipe(clean_func).dropna() # ✅
另外,inplace=True 在未来 pandas 版本中已被标记为弃用,建议从现在起习惯返回新 DataFrame 的写法。
真正容易被忽略的是:缺失值判定依赖 pd.options.mode.use_inf_as_na 设置。如果数据含 np.inf,默认不视作缺失;想让它也被删,得提前设 pd.set_option('mode.use_inf_as_na', True)。


















