表中的加权平均数

2024-04-19 16:21:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试生成pandas pivot表,该表计算一系列数据列中的值的平均值,这些值由固定权重列中的值加权,我正在努力找到一种优雅而高效的方法来实现这一点

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_表中滚动我自己的aggfunc,从而计算加权平均值


Tags: columns数据方法dataframepandasdfeasygroup
2条回答

下面是一种使用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

这适用于多个数字列:

创建一个使用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

相关问题 更多 >