pandas.DataFrame执行groupby操作时逐列剔除离群值的实现方法
解决方案
方案1:分组内按列剔除离群值后计算均值(推荐,符合分组统计的常规逻辑)
直接通过groupby+自定义聚合函数实现,无需手动遍历列,pandas会自动将每个分组的每列数据传入自定义函数处理:
import pandas as pd import numpy as np import string import random # 构造测试数据集 df = pd.DataFrame([]) df['A'] = pd.Series(np.random.normal(size=1000)) df['B'] = pd.Series(np.random.normal(size=1000, loc=-5, scale=1)) df['C'] = pd.Series(np.random.normal(size=1000, loc=10, scale=2)) df['index'] = pd.Series([random.choice(string.ascii_uppercase) for i in range(1000)]) # 自定义剔除离群值后求均值的函数 def mean_without_outlier(s: pd.Series): q1, q3 = s.quantile(0.25), s.quantile(0.75) iqr = q3 - q1 valid = s.between(q1 - 1.5*iqr, q3 + 1.5*iqr) return s[valid].mean() # 直接分组聚合即可,输出结构和原生groupby.mean完全一致 res = df.groupby('index').agg(mean_without_outlier)
该方案的特点是每个分组的每列独立计算IQR判定离群值,离群值仅在对应分组的对应列统计中被忽略,输出自动为26行(对应26个大写字母)、3列的DataFrame。
方案2:全局按列剔除离群值后分组计算均值
如果你的业务逻辑要求基于全量数据判定离群值,而非每个分组单独判定,可以用where将离群值替换为NaN,再分组求均值(mean方法会自动忽略NaN):
# 计算各列的全局IQR阈值 q1 = df[['A','B','C']].quantile(0.25) q3 = df[['A','B','C']].quantile(0.75) iqr = q3 - q1 lower, upper = q1 - 1.5*iqr, q3 + 1.5*iqr # 离群值替换为NaN df[['A','B','C']] = df[['A','B','C']].where(df[['A','B','C']].between(lower, upper)) # 分组求均值 res = df.groupby('index').mean()
内容的提问来源于stack exchange,提问作者phollox
相关产品推荐
相关产品推荐

