如何移除DataFrame所有列中偏离均值±3σ的异常值?代码留存率过低
问题
我有一个包含1168行、270列的DataFrame,目标是移除所有270列中偏离均值±3标准差的异常值。使用以下代码后仅保留了40个数据点(仅占原数据集的3%),不符合预期:
from scipy import stats len(df[(np.abs(stats.zscore(df)) < 3).all(axis=1)])
核心原因
当前代码要求每行的所有270列z-score都必须落在±3范围内才保留,高维场景下这种“全列无异常”的过滤逻辑过于严苛——只要任意一列有数据超出±3σ,整行就会被剔除,自然会导致大部分数据被误删。
改进方案
根据不同业务需求,提供几种更合理的处理方式:
1. 允许部分列存在异常值(按行过滤)
如果目标是移除行内多数列都存在异常值的样本,可以设定可接受的异常列比例阈值,比如允许最多10%的列有异常值:
import numpy as np from scipy import stats # 计算每行中z-score超出±3σ的列占比 outlier_col_ratio = (np.abs(stats.zscore(df)) >= 3).mean(axis=1) # 保留异常列占比低于10%的行 filtered_df = df[outlier_col_ratio < 0.1] print(f"保留行数:{len(filtered_df)},占原数据比例:{len(filtered_df)/len(df):.1%}")
2. 按列单独处理异常值
如果想针对每一列单独清理异常值(而非整行删除),可以选择填充或仅删除该列的异常行:
- 填充方式(用中位数替代异常值,比均值更鲁棒):
from scipy import stats for col in df.columns: z_scores = np.abs(stats.zscore(df[col])) # 用中位数替换该列的异常值 df.loc[z_scores >= 3, col] = df[col].median()
- 单列删除方式(仅移除指定列存在异常值的行):
target_column = "需要处理的列名" z_scores = np.abs(stats.zscore(df[target_column])) filtered_df = df[z_scores < 3]
3. 改用鲁棒性更强的异常值检测方法
z-score依赖正态分布假设,对极端值敏感,高维数据下可以改用IQR(四分位距)方法:
def filter_outliers_by_iqr(df, iqr_multiplier=1.5): filtered_df = df.copy() for col in df.columns: q1 = df[col].quantile(0.25) q3 = df[col].quantile(0.75) iqr_range = q3 - q1 lower_limit = q1 - iqr_multiplier * iqr_range upper_limit = q3 + iqr_multiplier * iqr_range filtered_df = filtered_df[(filtered_df[col] >= lower_limit) & (filtered_df[col] <= upper_limit)] return filtered_df filtered_df = filter_outliers_by_iqr(df) print(f"保留行数:{len(filtered_df)},占原数据比例:{len(filtered_df)/len(df):.1%}")
内容的提问来源于stack exchange,提问作者Katsu
相关产品推荐
相关产品推荐

