目标:获取一个 DataFrame,按该 DataFrame 的两列进行分组,计算第三列的加权平均值,并返回一个 DataFrame。下面的 Reprex 需要进行哪些调整?
## REPREX
import pandas as pd
import numpy as np
# Turn into DataFrame
md = {"group1": ["A", "A", "B", "B", "A"],
"group2": [1, 0, 1, 1, 1],
"var1":[343, 345, 567, 345, 212],
"wt":[1.2, 1.3, 1.8, .9, 1.9]}
# Turn into DataFrame
my_df = pd.DataFrame(md)
# This works to get unweighted means:
grouped__means = my_df.groupby(["group1", "group2"], as_index=False)[["var1"]].mean()
# This does NOT work for weighted means:
grouped__wtd_means = my_df.groupby(["group1", "group2"], as_index=False)[["var1"]].agg(np.average(weights=my_df["wt"]))
# What needs to change?
您可以在这里使用
GroupBy.apply
。
df.groupby(['group1', 'group2']).apply(lambda x: np.average(x['var1'], weights=x['wt']))
group1 group2
A 0 345.000000
1 262.709677
B 1 493.000000
dtype: float64
许多小组自己计算加权平均值以避免申请。将值乘以权重和总和,然后除以权重总和。
pandas
将在分区索引上对齐。
(df['var1'].mul(df['wt']).groupby([df['group1'], df['group2']]).sum()
.divide(df.groupby(['group1', 'group2'])['wt'].sum()))
group1 group2
A 0 345.000000
1 262.709677
B 1 493.000000
dtype: float64
另一种方法是将
set_index
与GroupBy.agg
结合使用。
例如在你的情况下:
(
my_df
.set_index('wt')
.groupby(["group1", "group2"])
.agg({'var1': lambda ser : np.average(ser, weights=ser.index)})
)