如何按Name分组结合权重列表计算加权平均值?
解决方案
首先修正你代码中的错误(dpid应为Name),然后通过分组自定义函数实现按Name计算加权平均的需求。以下是两种实用实现方式:
方式1:生成各组加权平均汇总表
适合需要单独查看每个组加权结果的场景:
import pandas as pd import numpy as np data = [ ['A',1,2,3,4], ['A',5,6,7,8], ['A',9,10,11,12], ['B',13,14,15,16], ['B',17,18,19,20], ['B',21,22,23,24], ['B',25,26,27,28], ['C',29,30,31,32], ['C',33,34,35,36], ['C',37,38,39,40], ] df = pd.DataFrame(data, columns=['Name', 'num1', 'num2', 'num3', 'num4']) def calculate_weighted_avg(group): n = len(group) # 按你的例子定义各组权重 if n == 3: weights = [30, 30, 40] elif n == 4: weights = [10, 20, 30, 40] else: weights = [100/n]*n # 其他长度组默认平均分配权重 # 计算加权平均:(数值*权重)求和后除以权重总和 weighted_avg = (group[['num1','num2','num3','num4']] * weights).sum() / sum(weights) return weighted_avg # 按Name分组计算并生成汇总表 weighted_avg_df = df.groupby('Name').apply(calculate_weighted_avg).reset_index() print(weighted_avg_df)
运行结果:
Name num1 num2 num3 num4 0 A 6.0 7.0 8.0 9.0 1 B 21.0 22.0 23.0 24.0 2 C 34.0 35.0 36.0 37.0
验证你的例子:
- 组A的num1:
(1*30 +5*30 +9*40)/100 = 540/100 = 6.0,符合预期 - 组B的num1:
(13*10+17*20+21*30+25*40)/100 = 2100/100 =21.0,符合预期
方式2:将加权平均填充到原DataFrame每行
适合需要保留原数据结构,同时替换为组内加权平均的场景:
def fill_weighted_avg(group): n = len(group) if n ==3: weights = [30,30,40] elif n ==4: weights = [10,20,30,40] else: weights = [100/n]*n weighted_avg = (group[['num1','num2','num3','num4']] * weights).sum() / sum(weights) # 将加权平均广播到组内所有行 group[['num1','num2','num3','num4']] = weighted_avg.values return group # 应用到原DataFrame df_weighted = df.groupby('Name').apply(fill_weighted_avg).reset_index(drop=True) print(df_weighted)
运行结果:
Name num1 num2 num3 num4 0 A 6.0 7.0 8.0 9.0 1 A 6.0 7.0 8.0 9.0 2 A 6.0 7.0 8.0 9.0 3 B 21.0 22.0 23.0 24.0 4 B 21.0 22.0 23.0 24.0 5 B 21.0 22.0 23.0 24.0 6 B 21.0 22.0 23.0 24.0 7 C 34.0 35.0 36.0 37.0 8 C 34.0 35.0 36.0 37.0 9 C 34.0 35.0 36.0 37.0
通用化调整(按组内行位置匹配权重列表)
如果你的weights = [10,20,30,40]是通用规则,组内第i行对应列表第i个权重(行数不足时取前n个),只需修改权重获取逻辑:
weights = [10,20,30,40] def calculate_weighted_avg(group): n = len(group) group_weights = weights[:n] weighted_avg = (group[['num1','num2','num3','num4']] * group_weights).sum() / sum(group_weights) return weighted_avg
内容的提问来源于stack exchange,提问作者Bad Coder
相关产品推荐
相关产品推荐

