基于多类别数据使用groupby结合Tukey Fence法去除异常值
使用Pandas Groupby + Transform 实现Tukey Fence异常值标记
不用循环拆分合并,直接用Pandas的groupby结合transform就能一步完成分组计算和异常值标记,代码简洁高效:
import pandas as pd # 示例数据(替换成你的实际数据) df = pd.DataFrame({ 'date': [1,2,3,4,1,2,3,4], 'prod': ['a','a','a','a','b','b','b','b'], 'units': [100,90,80,15,200,180,190,30000] }) # 定义Tukey Fence异常值判断逻辑 def mark_outliers(series): q1 = series.quantile(0.25) q3 = series.quantile(0.75) iqr = q3 - q1 lower = q1 - 1.5 * iqr upper = q3 + 1.5 * iqr # 异常值标记为1,正常为0 return ((series < lower) | (series > upper)).astype(int) # 按产品分组计算,生成flag列 df['flag'] = df.groupby('prod')['units'].transform(mark_outliers)
代码说明
groupby('prod')['units'].transform(mark_outliers):对每个产品组的units列应用异常值判断函数,transform会自动将计算结果与原数据行对齐,直接生成新列。- 自定义函数
mark_outliers中,先计算每组的四分位数和IQR,再判断每个数值是否超出Tukey边界,最后转为整数类型的标记。
运行后输出结果完全符合预期:
date prod units flag 0 1 a 100 0 1 2 a 90 0 2 3 a 80 0 3 4 a 15 1 4 1 b 200 0 5 2 b 180 0 6 3 b 190 0 7 4 b 30000 1
可选紧凑写法
如果不想单独定义函数,也可以用agg计算分组统计量后合并判断:
# 计算每组的Tukey边界 group_bounds = df.groupby('prod')['units'].agg( lower=lambda x: x.quantile(0.25) - 1.5*(x.quantile(0.75)-x.quantile(0.25)), upper=lambda x: x.quantile(0.75) + 1.5*(x.quantile(0.75)-x.quantile(0.25)) ) # 合并边界并标记异常值 df = df.merge(group_bounds, on='prod') df['flag'] = ((df['units'] < df['lower']) | (df['units'] > df['upper'])).astype(int) df = df.drop(['lower', 'upper'], axis=1)
内容的提问来源于stack exchange,提问作者Fernando Quintino
相关产品推荐
相关产品推荐

