用pandas.read_csv()配合na_values、keep_default_na和dtype可解决缺失值识别;异常值需按业务定义,用布尔索引或pd.to_numeric(errors="coerce")处理,避免硬套3σ等统计阈值。

直接说结论:用 pandas.read_csv() 配合 na_values、keep_default_na 和 dtype 参数,能一次性解决大部分缺失值识别问题;异常值则要先明确业务定义,再用布尔索引或 numpy.isfinite() 等做筛选——硬套统计阈值(比如 3σ)在真实 CSV 里经常误杀。
怎么让 read_csv() 正确识别“空”和“脏”字符串为缺失值
CSV 里写的是 "N/A"、"NULL"、"" 或空格,但默认只认 "NaN"、"null" 等有限几个。不显式声明,这些值会变成字符串类型,后续 isna() 判定全为 False。
- 用
na_values=["N/A", "NULL", "", " ", "missing"]显式列出所有表示缺失的文本 - 加
keep_default_na=False防止 pandas 把本意是正常字符串的"NaN"也转成np.nan - 对数值列提前指定
dtype={"age": "float64"},避免读入后因混入字符串而变成object类型,导致后续计算报错
为什么 df.dropna() 有时删不干净,甚至删掉整行
默认 how="any",只要某行任意一列是 NaN 就删——但真实数据里常有“部分字段缺失但其他字段有效”的情况,比如用户注册时跳过了可选字段。盲目全删等于丢数据。
- 按列控制:用
subset=["email", "phone"]只检查关键字段是否缺失 - 按比例保留:用
thresh=3表示每行至少要有 3 个非空值才保留 - 注意
inplace=True是就地修改,但返回值是None,别写成df = df.dropna(...)再赋值,否则可能意外覆盖
如何判断和替换数值列里的异常值(不是缺失值)
异常值 ≠ 缺失值。比如年龄列出现 -5、200 或 999,这些是有效字符串/数字,isna() 查不出来,但业务上不合理。
- 先用
pd.to_numeric(df["age"], errors="coerce")把非法字符串(如"abc")转成NaN,再统一处理 - 业务规则优先:比如年龄应在
0–120,用df.loc[~df["age"].between(0, 120), "age"] = np.nan - 避免直接用
df["age"] > df["age"].quantile(0.99)做截断——离群点本身可能拉高分位数,导致漏判
写回 CSV 时,nan 变成空字符串或特定标记的坑
默认 to_csv() 把 np.nan 输出为空字段(即两个逗号之间啥也没有),但下游系统可能期望写成 "N/A" 或留空格,甚至要求不输出该行。
- 用
na_rep="N/A"统一替换所有NaN输出为指定字符串 - 若想彻底剔除含
NaN的行再写入,必须先调用dropna(),to_csv()不接受skipna这类参数 - 注意
index=False,否则第一列会多出无意义的行号,被误认为数据列
最麻烦的其实是缺失值的语义差异:同一个 "-" 在“电话”列代表“未提供”,在“订单金额”列可能代表“免单”,不能无脑填 0 或删行。处理前务必确认字段业务含义,比写代码花的时间还多。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











