我正在尝试生成pandas数据透视表,该表计算一系列数据列中的值的平均值,这些数据列由固定权重列中的值加权,并努力寻找一种优雅而有效的方式来做到这一点。
>df = pd.DataFrame([['A',10,1],['A',20,0],['B',10,1],['B',0,0]],columns=['Group','wt','val'])
Group wt val
0 A 10 1
1 A 20 0
2 B 10 1
3 B 0 0
我想按组分组并返回新的权重(df.wt的总和-easy peasy)和由df.wt加权的df.val的平均值,以得出以下结果:
Group weight val
0 A 30 0.333
1 B 10 1.000
在实际的应用程序中,有大量的val列和一个weight列,以及我要向其应用不同aggfuncs的其他列。因此,尽管我意识到我可以通过直接应用groupby来做到这一点,但它更麻烦。有没有一种方法可以在pivot_table中滚动我自己的agfunc,从而可以计算加权平均值?
答案 0 :(得分:1)
这里是groupby
的一种方法:
(df.assign(total=df.wt*df.val)
.groupby('Group', as_index=False)
.sum()
.assign(val=lambda x: x['total']/x['wt'])
.drop('total', axis=1)
)
输出:
Group wt val
0 A 30 0.333333
1 B 10 1.000000
更新:对于所有val
类列:
# toy data
df = pd.DataFrame([['A',10,1,1],['A',20,0,1],['B',10,1,2],['B',0,0,1]],
columns=['Group','wt','val_a', 'val_b'])
# grouping sum
new_df = (df.filter(like='val') # filter val columns
.mul(df.wt, axis=0) # multiply with weights
.assign(wt=df.wt) # attach weight
.groupby(df.Group).sum()
)
# loop over columns and divide the weight sum
new_df.apply(lambda x: x/new_df['wt'] if x.name != 'wt' else x)
输出:
val_a val_b wt
Group
A 0.333333 1.0 30
B 1.000000 2.0 10
答案 1 :(得分:0)
这应该适用于多个数字列:
创建一个使用numpy average(包括权重)的函数。
对groupby中的组运行列表理解,并应用该功能
连接输出
df = pd.DataFrame([['A',10,1,2],['A',20,0,3],['B',10,1,2],['B',0,0,3]],columns=['Group','wt','val','vala'])
Group wt val vala
0 A 10 1 2
1 A 20 0 3
2 B 10 1 2
3 B 0 0 3
#create function
def avg(group):
df = pd.DataFrame()
for col in group.columns.drop(['Group','wt']):
A = group[col]
B = group['wt']
df['Group'] = group['Group'].unique()
df['wt'] = B.sum()
df[col] = np.average(A, weights=B)
return df
#pipe function to the group in the list comprehension
output = [group.pipe(avg) for name, group in df.groupby('Group')]
#concatenate dataframes
pd.concat(output,ignore_index=True)
Group wt val vala
0 A 30 0.333333 2.666667
1 B 10 1.000000 2.000000