Pandas 数据透视表/groupby 计算加权平均值

Posted

技术标签:

【中文标题】Pandas 数据透视表/groupby 计算加权平均值【英文标题】:Pandas pivot table / groupby to calculate weighted average 【发布时间】:2019-12-30 06:45:38 【问题描述】:

我正在使用 pandas 版本 0.25.0 来计算定价合约的加权平均值。

数据:

'Counterparty': 0: 'A',
  1: 'B',
  2: 'B',
  3: 'A',
  4: 'A',
  5: 'C',
  6: 'D',
  7: 'E',
  8: 'E',
  9: 'C',
  10: 'F',
  11: 'C',
  12: 'C',
  13: 'G',
 'Contract': 0: 'A1',
  1: 'B1',
  2: 'B2',
  3: 'A2',
  4: 'A3',
  5: 'C1',
  6: 'D1',
  7: 'E1',
  8: 'E2',
  9: 'C2',
  10: 'F1',
  11: 'C3',
  12: 'C4',
  13: 'G',
 'Delivery': 0: '1/8/2019',
  1: '1/8/2019',
  2: '1/8/2019',
  3: '1/8/2019',
  4: '1/8/2019',
  5: '1/8/2019',
  6: '1/8/2019',
  7: '1/8/2019',
  8: '1/8/2019',
  9: '1/8/2019',
  10: '1/8/2019',
  11: '1/8/2019',
  12: '1/8/2019',
  13: '1/8/2019',
 'Price': 0: 134.0,
  1: 151.0,
  2: 149.0,
  3: 134.0,
  4: 132.14700000000002,
  5: 150.0,
  6: 134.566,
  7: 153.0,
  8: 151.0,
  9: 135.0,
  10: 149.0,
  11: 135.0,
  12: 147.0,
  13: 151.0,
 'Balance': 0: 200.0,
  1: 54.87,
  2: 200.0,
  3: 133.44,
  4: 500.0,
  5: 500.0,
  6: 1324.05,
  7: 279.87,
  8: 200.0,
  9: 20.66,
  10: 110.15,
  11: 100.0,
  12: 100.0,
  13: 35.04

方法一:

df.pivot_table(
    index=['Counterparty', 'Contract'],
    columns='Delivery',
    values=['Balance', 'Price'],
    aggfunc=
        'Balance': sum,
        'Price': np.mean
    ,
    margins=True
).fillna('').swaplevel(0,1,axis=1).sort_index(axis=1).round(3)

结果 1:

有什么方法可以在 pandas 数据透视表中使用 np.average 吗? 沿着思路思考

aggfunc = 
    'Balance': sum,
    'Price': lambda x: np.average(x, weights='Balance')

当前结果:143.265,由 np.mean 计算得出。

期望结果:140.424,这是PriceBalance 的加权平均值。

方法二:

df_grouped = df.groupby(['Counterparty', 'Contract', 'Delivery']).apply(lambda x: pd.Series(
                
                    'Balance': x['Balance'].sum(),
                    'Price': np.average(x['Price'], weights=x['Balance']),
                
                )).round(3).unstack().swaplevel(0,1, axis=1).sort_index(axis=1)

结果 2:

使用 groupby,我需要将 pd.concatappend 逐级求和才能得到 aggfunc = Balance: sum, Price: np.average 的总计。

预期结果是:

Balance: 3758.08 (using sum)
Price: 140.424 (using np.average)

显示在所有数据行下方的总计行中。

【问题讨论】:

【参考方案1】:

只需定义一个自定义函数来计算加权平均值,并在代码中将其与aggfunc 一起使用,而不是np.mean,如下所示:

wa_func =lambda x: np.average(x, weights=df.loc[x.index, 'Balance'])

df1 = df.pivot_table(
    index=['Counterparty', 'Contract'],
    columns='Delivery',
    values=['Balance', 'Price'],
    aggfunc=
        'Balance': sum,
        'Price': wa_func
    ,
    margins=True
).fillna('').swaplevel(0,1,axis=1).sort_index(axis=1).round(3)

Out[35]:
Delivery              1/8/2019               All
                       Balance    Price  Balance    Price
Counterparty Contract
A            A1         200.00  134.000   200.00  134.000
             A2         133.44  134.000   133.44  134.000
             A3         500.00  132.147   500.00  132.147
B            B1          54.87  151.000    54.87  151.000
             B2         200.00  149.000   200.00  149.000
C            C1         500.00  150.000   500.00  150.000
             C2          20.66  135.000    20.66  135.000
             C3         100.00  135.000   100.00  135.000
             C4         100.00  147.000   100.00  147.000
D            D1        1324.05  134.566  1324.05  134.566
E            E1         279.87  153.000   279.87  153.000
             E2         200.00  151.000   200.00  151.000
F            F1         110.15  149.000   110.15  149.000
G            G           35.04  151.000    35.04  151.000
All                    3758.08  140.424  3758.08  140.424

【讨论】:

只是为了跟进这个问题..如果我想按“平衡”从大到小对 df 进行排序,我将如何完成它?已尝试执行 .sort_values([('Balance', 'Price')], ascending=False),但它说没有找到任何键。参考:***.com/questions/14733871/…

以上是关于Pandas 数据透视表/groupby 计算加权平均值的主要内容,如果未能解决你的问题,请参考以下文章

group的加权平均值不等于pandas groupby中的总平均值

Pandas Groupby 加权标准差

python pandas groupby分组后的数据怎么用

pandas聚合和分组运算之groupby

如何在 Pandas 中的超大数据框上创建数据透视表

Pandas 数据透视表百分比计算