Python pandas groupby聚合时如何计算加权中位数并聚合多列
问题根因
原有代码无法运行有3个直接问题:
- 在
groupby().agg()的字典传参规则中,针对单个列传入的聚合函数,仅能接收到当前列的分组切片,无法直接读取同组下其他列的数据,直接引用TotalCost无法获取分组内对应的权重值。 wquantiles库的加权中位数接口调用错误,该库的加权中位数方法为顶级方法wquantiles.median(),不存在weighted.median的调用路径。- 未正确导入对应方法,直接调用
weighted.median会触发名称未定义错误。
正确实现代码
方案1:基于wquantiles库实现
import pandas as pd import wquantiles # 构造测试数据 data={'Date':['2022-03-01','2022-03-01','2022-03-01','2022-03-01', '2022-04-01', '2022-04-01', '2022-04-01'],'Item':['AB','AB','AB','AC', 'AB', 'AC', 'AC'],'BetterPrice':[0,0,1,1, 1, 1, 0],'TotalCost':[200,200,300,400, 400, 100, 50],'Location':[3,2,3,2,1,3, 1]} df=pd.DataFrame(data) # 分组聚合逻辑 def group_agg_calc(group): return pd.Series({ 'BetterPrice_sum': group['BetterPrice'].sum(), 'Location_weighted_median': wquantiles.median(group['Location'], weights=group['TotalCost']) }) df_result = df.groupby(['Date', 'Item']).apply(group_agg_calc).reset_index()
运行后得到的结果如下:
| Date | Item | BetterPrice_sum | Location_weighted_median |
|---|---|---|---|
| 2022-03-01 | AB | 1 | 3 |
| 2022-03-01 | AC | 1 | 2 |
| 2022-04-01 | AB | 1 | 1 |
| 2022-04-01 | AC | 1 | 3 |
方案2:无第三方依赖自实现
如果不想安装wquantiles库,可以自己实现加权中位数逻辑,计算结果和库方法一致:
def weighted_median(values, weights): # 按计算值升序配对排序 sorted_val_weights = sorted(zip(values, weights), key=lambda x: x[0]) total_weight = sum(weights) cum_weight = 0 half_weight = total_weight / 2 for val, w in sorted_val_weights: cum_weight += w if cum_weight >= half_weight: return val # 替换聚合函数即可 def group_agg_calc(group): return pd.Series({ 'BetterPrice_sum': group['BetterPrice'].sum(), 'Location_weighted_median': weighted_median(group['Location'], weights=group['TotalCost']) }) df_result = df.groupby(['Date', 'Item']).apply(group_agg_calc).reset_index()
说明
如果一定要用agg方法实现,本质上还是需要解决跨列取权重的问题,写法会比apply冗余很多,可读性差,没有特殊要求的话优先用apply处理跨列分组聚合场景即可。
内容的提问来源于stack exchange,提问作者rightleftdownup313
相关产品推荐
相关产品推荐

