我的知识记录

Python处理异常值outliers检测与处理教程

用箱线图IQR法和3σ标准差法检测数据中的异常值,提供删除、截断、替换三种处理方式,适合销售数据、工资数据的清洗。

场景痛点

业务报表里突然冒出来一笔100万的订单,或者员工工资表混进一个1000万的样本,不处理的话平均值被拉飞,领导看了报表要骂。手动一个个找异常值眼睛花,用IQR箱线图法和3σ法自动识别,再决定删除还是截断,几分钟搞定。

用到的库

pip install pandas numpy

完整代码

import pandas as pd
import numpy as np

def sample_df():
return pd.DataFrame({
"name":   ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛"],
"salary": [12000, 15000, 13000, 14000, 12500, 16000, 11000, 90000],
})

def iqr_method(s: pd.Series):
"""IQR箱线图法:超出 [Q1-1.5*IQR, Q3+1.5*IQR] 视为异常"""
q1 = s.quantile(0.25)
q3 = s.quantile(0.75)
iqr = q3 - q1
low, high = q1 - 1.5 * iqr, q3 + 1.5 * iqr
mask = (s < low) | (s > high)
return mask, low, high

def sigma_method(s: pd.Series):
"""3σ法:偏离均值3个标准差之外视为异常"""
mean = s.mean()
std = s.std()
low, high = mean - 3 * std, mean + 3 * std
mask = (s < low) | (s > high)
return mask, low, high

def outliers_demo():
df = sample_df()
print("原始:")
print(df)

# IQR法
mask_iqr, low, high = iqr_method(df["salary"])
print(f"\nIQR法阈值:[{low:.0f}, {high:.0f}]")
print("异常值:")
print(df[mask_iqr])

# 处理方式1:直接删除
df_clean = df[~mask_iqr].copy()
print(f"\n删除异常值后剩余 {len(df_clean)} 行")

# 处理方式2:截断到上下限(winsorize)
df["salary_winsor"] = df["salary"].clip(lower=low, upper=high)
print("\n截断处理后:")
print(df)

# 处理方式3:用中位数替换
median = df["salary"].median()
df.loc[mask_iqr, "salary_median"] = median
df.loc[~mask_iqr, "salary_median"] = df["salary"]
print("\n中位数替换后:")
print(df[["name", "salary", "salary_median"]])

if __name__ == "__main__":
outliers_demo()

代码讲解

  • IQR法:Q1是25%分位数,Q3是75%分位数,IQR=Q3-Q1。异常值定义为小于Q1-1.5IQR或大于Q3+1.5IQR,对偏态分布(如收入)很稳健。
  • 3σ法:正态分布下99.7%的数据落在±3σ内,适合近似正态的数据。工资、销售额通常右偏,IQR更合适。
  • 三种处理:删除 df[~mask] 最简单;clip(lower, upper) 截断到边界,保留样本量;中位数替换适合异常比例不高的情况。
  • 处理前先 df[mask] 看一眼具体是哪些行,确认是真异常还是业务极值(比如大客户),别误删。

运行结果

控制台打印原始8行数据,其中辛的90000是异常值。IQR法识别出辛为异常,删除后剩7行;截断后辛的工资被压到上限;中位数替换后辛的工资换成中位数13250。

注意事项

  • 异常值不一定是错的:90000可能是CEO真实工资,业务上要保留,统计分析时才处理。
  • 同一列不同业务线分布不同,应分组检测:df.groupby("dept")["salary"].apply(...) 分别识别。
  • 客户金额、订单量这类对数正态分布数据,先 np.log() 再检测异常值更合理。
  • 处理完要把原始列和处理后列都保留,方便回溯。

Python处理异常值outliers检测与处理教程

标签:

更新时间:2026-09-14 20:58:27

上一篇:Python pandas apply自定义函数教程

下一篇:Python嵌套JSON展开打平教程:扁平化嵌套字段