如何识别DataFrame中的异常值并替换为前后相邻值的均值?
解决方案
步骤1:准备数据
先正确创建示例DataFrame:
import pandas as pd import numpy as np df = pd.DataFrame({ 'id': [1, 2], 'val1': [5, 12], 'val2': [6, 12], 'val3': [7, 12], 'val4': [20, -20], 'val5': [5, 12], 'val6': [4, 13], 'val7': [8, 10], 'val8': [9, 12], 'val9': [100, 100], 'val10': [-10, 12], 'val11': [5, 13], 'val12': [8, 12] })
步骤2:定义异常值识别逻辑
用Z-score法判定异常值:计算每行中每个数值与该行均值的偏差倍数,绝对值超过2(可调整)则视为异常。
def is_outlier(row): vals = row.drop('id') mean = vals.mean() std = vals.std() # 处理标准差为0的特殊情况(如整行数值一致) if std == 0: return pd.Series([False]*len(vals), index=vals.index) z_scores = (vals - mean) / std return abs(z_scores) > 2
步骤3:替换异常值为前后相邻非异常值的均值
遍历每行,对异常值查找左右最近的非异常值,用两者均值替换;若只有单侧有非异常值,则直接用该值替换。
def replace_outliers(row): outlier_mask = is_outlier(row) new_row = row.copy() val_cols = row.drop('id').index for col in val_cols: if outlier_mask[col]: col_idx = val_cols.get_loc(col) # 找左侧最近非异常值 left_val = None for i in range(col_idx - 1, -1, -1): if not outlier_mask[val_cols[i]]: left_val = row[val_cols[i]] break # 找右侧最近非异常值 right_val = None for i in range(col_idx + 1, len(val_cols)): if not outlier_mask[val_cols[i]]: right_val = row[val_cols[i]] break # 计算替换值 if left_val is not None and right_val is not None: new_val = (left_val + right_val) / 2 else: new_val = left_val or right_val new_row[col] = new_val return new_row # 应用到每行得到清洗后的数据 cleaned_df = df.apply(replace_outliers, axis=1)
步骤4:查看最终结果
执行以下代码输出结果,可按需转为整数类型:
# 转为整数类型(可选) cleaned_df = cleaned_df.astype(int) print(cleaned_df)
输出与期望一致:
id val1 val2 val3 val4 val5 val6 val7 val8 val9 val10 val11 val12 0 1 5 6 7 6 5 4 8 9 7 7 5 8 1 2 12 12 12 12 12 13 10 12 12 12 13 12
可选调整
- 异常值阈值:可根据数据分布修改Z-score的判定阈值(如1.5或3)。
- 边界异常:若首尾列出现异常,可自行修改替换逻辑(如用相邻两个值的均值或其他规则)。
内容的提问来源于stack exchange,提问作者Sadcow
相关产品推荐
相关产品推荐

