You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何移除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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 07:25:23