如何使用transform筛选分组中的最大值和最小值行
筛选十分位分组的最大/最小值行
需求
筛选每个十分位分组中score字段为最大值或最小值的行,保留这些行以分析各十分位的数值变化。
数据准备
先生成测试数据:
np.random.seed(0) df = pd.DataFrame({'id' : range(1,31), 'score' : np.random.uniform(size = 30)}) df
添加十分位列,将score分成10个等分组:
df['decile'] = pd.qcut(df['score'], 10, labels=False)
尝试的错误写法
以下两种写法均无法正常运行:
写法一
df.transform((df['score'] == df.groupby('decile')['score'].min()) or (df['score'] == df.groupby('decile')['score'].max()))
写法二
df.transform(df['score'].eq(df.groupby('decile')['score'].min().values).any() or df['score'].eq(df.groupby('decile')['score'].max().values).any())
正确解法
问题分析
- 不能用
or处理布尔Series,需用按位或运算符|; - 直接比较原Series和分组聚合结果会出现索引不匹配,需用
groupby.transform将组内统计量广播到每一行; transform的使用场景不对,这里核心是筛选行,不是转换数据。
方法一:生成临时列后筛选
先通过transform得到每个分组的min/max,再匹配筛选:
# 生成每个分组的min和max,广播到对应行 df['group_min'] = df.groupby('decile')['score'].transform('min') df['group_max'] = df.groupby('decile')['score'].transform('max') # 筛选目标行 result = df[(df['score'] == df['group_min']) | (df['score'] == df['group_max'])] # 移除临时列 result = result.drop(['group_min', 'group_max'], axis=1)
方法二:分组后直接过滤
用groupby.apply对每个分组单独筛选:
def filter_min_max(group): return group[(group['score'] == group['score'].min()) | (group['score'] == group['score'].max())] result = df.groupby('decile').apply(filter_min_max).reset_index(drop=True)
方法三:链式简洁写法
用lambda函数结合transform直接生成筛选条件:
result = df[df.groupby('decile')['score'].transform(lambda x: (x == x.min()) | (x == x.max()))]
运行以上任意一种方法,即可得到每个十分位分组中score为最大值或最小值的行。
内容的提问来源于stack exchange,提问作者Karthik S
相关产品推荐
相关产品推荐

