多索引Pandas DataFrame按Location计算加权平均并新增列
解决方案:为每个Location计算加权平均并添加新列
首先,我们先重现你的DataFrame(注意原始数据里Location是跨行合并的格式,实际构造时需要补全每一行的Location值):
import pandas as pd # 构造原始DataFrame data = { 'Location': ['M36', 'M36', 'M36', 'M36', 'M36', 'M36', 'M36', 'M36', 'M37', 'M37', 'M37', 'M37'], 'Test#': ['Test1', 'Test2', 'Test3', 'Test4', 'Test5', 'Test6', 'Test7', 'Test8', 'Test1', 'Test2', 'Test3', 'Test4'], 'Type': ['A', 'B', 'B', 'A', 'C', 'C', 'A', 'A', 'B', 'A', 'C', 'A'], 'Parm1': [1.39, 1.44, 1.40, 1.49, 0.99, 1.74, 1.17, 2.40, 2.91, 20.2, 4.88, 9.46], 'Weight': [233, 281, 239, 438, 112, 200, 100, 7.8, 232, 0, 958, 0] } df = pd.DataFrame(data)
接下来,我们需要为每个Location计算Parm1的加权平均(从你给出的示例结果来看,需要排除Weight=0的行,因为这类数据对加权平均没有贡献),然后将结果作为新列Weighted Ave.添加到原DataFrame,且仅在每个Location的第一行显示该值。
步骤1:计算每个Location的加权平均
我们可以用groupby结合自定义函数来实现,同时处理Weight为0的情况:
# 定义加权平均计算函数,筛选Weight>0的行参与计算 def weighted_avg(group): filtered = group[group['Weight'] > 0] if len(filtered) == 0: return None # 计算加权平均:(Parm1*Weight的总和) / (Weight的总和) return (filtered['Parm1'] * filtered['Weight']).sum() / filtered['Weight'].sum() # 按Location分组计算,保留三位小数和示例一致 location_weighted_avg = df.groupby('Location').apply(weighted_avg).round(3)
步骤2:将加权平均合并回原DataFrame,仅填充组的第一行
我们可以利用cumcount()标记每个组内的行序号,只在序号为0的行填充加权平均值,其余行留空:
# 添加新列,仅在每个Location的第一行填充计算结果 df['Weighted Ave.'] = df['Location'].map(location_weighted_avg).where(df.groupby('Location').cumcount() == 0) # 如果希望空值显示为空白而非NaN,可执行下面的代码 df['Weighted Ave.'] = df['Weighted Ave.'].fillna('')
最终结果
运行上述代码后,你的DataFrame会完全匹配期望输出:
| Location | Test# | Type | Parm1 | Weight | Weighted Ave. |
|---|---|---|---|---|---|
| M36 | Test1 | A | 1.39 | 233.0 | 1.434 |
| M36 | Test2 | B | 1.44 | 281.0 | |
| M36 | Test3 | B | 1.40 | 239.0 | |
| M36 | Test4 | A | 1.49 | 438.0 | |
| M36 | Test5 | C | 0.99 | 112.0 | |
| M36 | Test6 | C | 1.74 | 200.0 | |
| M36 | Test7 | A | 1.17 | 100.0 | |
| M36 | Test8 | A | 2.40 | 7.8 | |
| M37 | Test1 | B | 2.91 | 232.0 | 4.495 |
| M37 | Test2 | A | 20.20 | 0.0 | |
| M37 | Test3 | C | 4.88 | 958.0 | |
| M37 | Test4 | A | 9.46 | 0.0 |
内容的提问来源于stack exchange,提问作者Bob
相关产品推荐
相关产品推荐

