Pandas带条件的分组自定义聚合是否可行?连续价差阈值分组聚合实现
解决方案
你可以对每个分组单独判断处理,而非直接全局聚合,这样既能筛选需要聚合的分组,也能在聚合时访问分组内所有列的数据。
完整实现代码
import pandas as pd # 原始数据和前置处理代码 df = pd.DataFrame( [{'price': 22, 'weight': 1, 'product': 'banana', }, {'price': 20, 'weight': 2, 'product': 'apple', }, {'price': 18, 'weight': 2, 'product': 'car', }, {'price': 100, 'weight': 1, 'product': 'toy', }, {'price': 27, 'weight': 1, 'product': 'computer', }, {'price': 200, 'weight': 1, 'product': 'book', }, {'price': 200.5, 'weight': 3, 'product': 'mouse', }, {'price': 202, 'weight': 3, 'product': 'door', },] ) df.sort_values(by=['price'], inplace=True) df['asc_diff'] = df['price'].diff(periods=1) df['desc_diff'] = df['price'].diff(periods=-1).abs() df['asc_diff'] = df['asc_diff'].combine_first(df['desc_diff']) df['asc_diff'] = df[['asc_diff', 'desc_diff']].min(axis=1).abs() df['asc_diff'] = df['asc_diff'] <= 2.0 df = df.drop(columns=['desc_diff']) g = df.groupby((df['asc_diff'].shift() != df['asc_diff']).cumsum()) # 分组处理逻辑 res_list = [] for group_id, group_df in g: # 同一分组的asc_diff值完全一致,取第一个判断即可 if group_df['asc_diff'].iloc[0]: # 符合条件的分组按规则聚合 agg_row = { # 计算price的加权平均值 'price': (group_df['price'] * group_df['weight']).sum() / group_df['weight'].sum(), 'weight': group_df['weight'].max(), 'product': ' '.join(group_df['product']), 'asc_diff': True } res_list.append(pd.DataFrame([agg_row])) else: # 不符合条件的分组直接保留原始行 res_list.append(group_df[['price', 'weight', 'product', 'asc_diff']]) # 合并所有处理结果 final_df = pd.concat(res_list, ignore_index=True) print(final_df)
运行输出结果
price weight product asc_diff 0 19.600000 2 car apple banana True 1 27.000000 1 computer False 2 100.000000 1 toy False 3 201.071429 3 book mouse door True
逻辑说明
- 遍历每个分组时先判断
asc_diff值,仅对值为True的分组执行聚合操作 - 聚合时直接操作整个分组的DataFrame,可以同时获取
price和weight列计算加权平均值 - 不需要聚合的分组直接返回原始行,保留所有原始数据结构
内容的提问来源于stack exchange,提问作者Eduardo Gomes
相关产品推荐
相关产品推荐

