isna() 与 isnull() 功能完全一致,isnull() 是 isna() 的别名;官方推荐新代码统一用 isna() 以语义更清晰;dropna() 默认仅删全空行,需显式设 how="any" 才删含空值行;空字符串""不被识别为缺失值,须先 replace 为 pd.na;删行后务必 reset_index(drop=true) 避免索引断裂。

用 isna() 还是 isnull()?它们完全一样
两者功能、返回值、行为 100% 一致,isnull() 是 isna() 的别名,纯为兼容旧代码保留。Pandas 官方文档明确建议新代码统一用 isna() —— 不是因为它更强,而是为了语义清晰(“is not available” 比 “is null” 更贴合缺失值本质)。
常见错误:在条件筛选里混用两者以为有差异,比如写 df[df.isnull().any(axis=1)] 和 df[df.isna().any(axis=1)],结果完全一样,没必要纠结选哪个,选 isna() 就行。
dropna() 默认只删全空行,不是你想要的“删掉含空值的行”
默认行为是:只要某行**所有列都为空(NaN/None)**,才被删除。这跟多数人直觉里的“删掉任何含空值的行”不符。
实操建议:
- 删掉**任意一列为空**的行 → 加参数
how="any"(这是最常用场景) - 删掉**所有列都为空**的行 → 用默认或显式
how="all" - 只对特定列判断是否空 → 用
subset=["col_a", "col_b"],避免误删其他列正常的行 - 原地修改不生成新 DataFrame → 加
inplace=True,但注意返回值是None,别链式调用
示例:df.dropna(how="any", subset=["age", "salary"]) 表示:只要 age 或 salary 中有一个为空,整行就删。
字符串空值('')、None、np.nan、pd.NA 都算缺失吗?
不算全算。默认情况下,isna() 和 dropna() 只识别 np.nan、None、pd.NA;**空字符串 "" 被当作有效值,不会被检测或删除**。
常见错误现象:用 dropna() 后发现还有大量空白行,其实是 "" 填充的,不是 NaN。
解决办法:
- 提前把空字符串转成
NaN:df.replace("", pd.NA).dropna() - 或用布尔索引组合判断:
df[~(df["col"] == "") & df["col"].isna()] - 注意:
pd.NA在较新 Pandas(1.0+)中启用扩展类型时才真正生效,老版本建议优先用np.nan
删完行后索引乱了?别忘了重置
dropna() 不会自动重排索引,删掉中间几行后,Index 可能变成 [0, 1, 2, 5, 6, 9] —— 看起来怪,后续用 .iloc[3] 会取错行,merge 或 plot 也可能出问题。
实操建议:
- 删完立刻接
.reset_index(drop=True),drop=True是关键,否则老索引变新列 - 如果要保留原始索引作标记,改用
reset_index()(不加drop),但得意识到多了一列 - 别在管道里漏掉这步,尤其做批量清洗时,索引断裂是后期 debug 最隐蔽的坑之一
示例:df.dropna(how="any").reset_index(drop=True)
缺失值处理真正麻烦的从来不是函数怎么写,而是搞不清数据里到底混着几种“空”、哪些列该参与判断、删完要不要保索引——这些细节不盯住,跑十次 dropna() 都可能得到不同结果。










