基于99分位数分组去除Pandas数据异常值的问题求助
按分组基于99分位数移除异常值的正确实现
让我来帮你搞定这个问题!你尝试的代码之所以没得到预期结果,核心问题在于额外加入了x > x.quantile(0.01)的条件——在小样本数据中,0.01分位数通常等于组内最小值,这会把等于最小值的行(比如B组的3.3)错误过滤掉,不符合你的需求。
下面是几种符合你预期的正确实现方式:
方法一:仅过滤99分位数以上的异常值(完美匹配你的示例)
直接移除大于等于99分位数的数值(你的示例中要移除的正好是每组的99分位数对应值),代码如下:
import pandas as pd df = pd.DataFrame({'Group': ['A','A','A','B','B','B','B'], 'count': [1.1,11.2,1.1,3.3,3.40,3.3,100.0]}) # 按分组过滤掉大于99分位数的值 result_df = df[df.groupby("Group")['count'].transform(lambda x: x < x.quantile(0.99))] print(result_df)
运行后会输出你期望的结果:
Group count 0 A 1.1 2 A 1.1 3 B 3.3 4 B 3.4 5 B 3.3
为什么这个代码有效?
groupby("Group")['count'].transform(...)会为每一行计算其所在组的99分位数,返回与原数据长度一致的布尔数组;- 我们只保留
count值小于组内99分位数的行,正好移除了你示例中的A组11.2和B组100.0。
方法二:高效的非lambda实现(适合大数据集)
如果你处理的是大数据集,使用merge的方式性能更优,避免lambda的开销:
# 计算每组的99分位数并命名列 quant_99 = df.groupby('Group')['count'].quantile(0.99).rename('quant_99') # 合并分位数到原数据 df_with_quant = df.merge(quant_99, on='Group') # 过滤并清理多余列 result_df = df_with_quant[df_with_quant['count'] < df_with_quant['quant_99']].drop('quant_99', axis=1)
扩展:双向过滤1%以下和99%以上的异常值
如果你确实需要同时过滤两端的异常值,但不想过滤等于分位数的行,只需调整条件为>=和<=:
result_df = df[df.groupby("Group")['count'].transform(lambda x: (x >= x.quantile(0.01)) & (x <= x.quantile(0.99)))]
注意:在你的示例中,这个代码会保留A组的11.2(因为它等于99分位数),所以不符合你的预期;如果需要双向过滤且移除等于分位数的值,就用>和<。
内容的提问来源于stack exchange,提问作者Kumar AK
相关产品推荐
相关产品推荐

