当某列缺失值占比超过阈值(如70%)时应直接删除该列,因其建模价值低且插补易引入噪声;需用df.isnull().mean()计算各列缺失率,再布尔索引筛选并drop。

缺失值比例超过阈值就该直接删列,别犹豫
当某列缺失值占比超过 70%(或你设定的业务阈值),它基本丧失了建模价值,强行插补反而引入噪声。Python 中没有 dropna 直接按列缺失比例删除的功能——dropna 默认作用于行(axis=0),且只支持 thresh(保留至少 N 个非空值),不支持“保留缺失率低于 X% 的列”。必须手动计算比例再筛选。
用 isnull().mean() 快速算每列缺失率
这是最轻量、最可读的方式:df.isnull().mean() 返回每列缺失值占比(0~1 的 float Series),比 df.isnull().sum() / len(df) 更简洁,且自动对齐列名。
- 缺失率 > 0.7 的列:用布尔索引过滤列名,如
df.columns[df.isnull().mean() > 0.7] - 保留低缺失率列:直接重赋值
df = df.loc[:, df.isnull().mean() - 注意:
isnull()对数值型、字符串、None、NaN 都有效,但对pd.NaT(时间类型空值)也识别,无需额外处理
别用 dropna(thresh=...) 试图替代列过滤
dropna 的 thresh 参数是“保留至少 N 个非空值的行/列”,不是“缺失率阈值”。例如 df.dropna(axis=1, thresh=int(0.3 * len(df))) 看似等价,但有硬伤:
- 结果依赖
len(df),若后续 df 行数变化(如先切片再 dropna),阈值就错位 -
thresh接受整数,无法表达 69.8% 这类小数阈值,必须手动取整,易误删临界列 - 语义模糊:别人读代码时看不出你在控“缺失率”,只看到一个魔法数字
生产环境建议封装成函数并保留日志
实际项目中,删列不能悄无声息。应记录哪些列被剔除及原因,方便复盘和审计。
立即学习“Python免费学习笔记(深入)”;
def drop_high_missing_cols(df, threshold=0.7, verbose=True):
missing_ratio = df.isnull().mean()
to_drop = missing_ratio[missing_ratio > threshold].index.tolist()
if verbose and to_drop:
print(f"Drop {len(to_drop)} columns with missing ratio > {threshold}: {to_drop}")
return df.drop(columns=to_drop)调用时直接 df_clean = drop_high_missing_cols(df, threshold=0.65)。注意:该函数不修改原 df,避免副作用;若需原地修改,加 inplace=True 到 drop() 即可。
真正容易被忽略的是:缺失率计算前,要确认是否已做类型归一化——比如把字符串 "NULL"、"N/A" 显式转为 np.nan,否则 isnull() 会漏判。这步常在清洗早期做,但删列前必须检查到位。


















