非结构化缺失值在机器学习中并不存在,真正需处理的是伪装成有效值的隐性缺失(如"n/a"、空字符串)及跨类型列混杂导致的检测失效;isna()仅识别none、np.nan、pd.na、pd.nat,对字符串型隐性缺失无响应,须手动替换为pd.na并转为可空类型(如"string"、"int64")以确保dropna()、fillna()等操作正确生效。

非结构化缺失值在机器学习项目中根本不存在——Pandas 只处理结构化表格数据,所谓“非结构化缺失值”其实是误用术语。真正要解决的,是那些**伪装成有效值的隐性缺失**(如 "N/A"、"-"、空字符串 ""、零值 0 在本不该为零的字段中),以及**跨类型列混杂导致的检测失效**问题。
为什么 isna() 对 "n/a" 和 "" 完全没反应
isna() 只识别 None、np.nan、pd.NA 和 pd.NaT 这四类显式缺失标记。字符串 "n/a"、"NULL"、"--" 或空格串 " " 在 Pandas 里就是普通字符串,类型是 object 或 string,isna() 返回 False。
- 先用
df.select_dtypes("object").columns找出所有文本列 - 对每列手动检查常见隐性标记:
df[col].isin(["n/a", "N/A", "-", "", " ", "NULL", "null"]) - 把它们统一转为
pd.NA(推荐)或np.nan:df[col] = df[col].replace(["n/a", "-"], pd.NA) - 再调用
df[col] = df[col].astype("string")强制启用可空字符串类型,避免后续被自动转回object
dropna() 删除后行数暴减?可能是整行被误判为全空
默认 dropna() 对任何含 NaN 的行都删,但如果你之前把隐性缺失转成了 pd.NA,而列又是 object 类型,pd.NA 在 object 列中不被 dropna() 识别——结果就是该删的没删,不该删的反而因其他列的 NaN 被连坐删除。
- 务必在
dropna()前确认数据类型:df.dtypes,看到object就警惕 - 把文本列转为可空类型:
df[col] = df[col].astype("string")或df[col] = df[col].astype("boolean")(布尔列) - 数值列优先用
"Int64"、"Float64"等可空类型,避免float64中混入np.nan导致精度丢失 - 删除时明确指定范围:
df.dropna(subset=["age", "income"], how="any"),别依赖默认行为
用 fillna() 填了却报错 TypeError: cannot convert float NaN to integer
这是整型列里混入 np.nan 后最典型的报错。因为 np.nan 是浮点,而原始列是 int64,Pandas 拒绝用浮点填整型——但它又不会自动帮你升维,只会抛错。
- 根本解法:从源头禁用
int64,改用可空整型:df["col"] = df["col"].astype("Int64")(注意大写I) - 如果必须保留原类型,填之前先转浮点:
df["col"] = df["col"].astype("float64").fillna(0),但会损失整数语义 - 别用
df.fillna(0)全表填——它会对所有列生效,字符串列也会被填成0,破坏数据类型 - 填众数时注意:
df["category"].mode()[0]在无众数时会报错,加try/except或用df["category"].fillna(df["category"].mode().iloc[0] if not df["category"].mode().empty else "Unknown")
真正麻烦的不是填或删,而是隐性缺失和类型混乱交织在一起——比如一列标称“销量”,却混着 "暂无"、0、np.nan,三者语义完全不同,但 isna() 只认出最后一个。这种情况下,必须人工定义业务规则,而不是依赖通用函数。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











