【问题标题】:Calculating weighted average by GroupBy.agg and a named aggregation通过 GroupBy.agg 和命名聚合计算加权平均值
【发布时间】:2020-04-04 23:37:13
【问题描述】:

Pandas 0.25 版通过函数aggnamedtuples 支持“命名聚合”。您需要按照doc 的描述传递列、聚合器对。它还说:

如果您的聚合函数需要额外的参数,请使用 functools.partial() 部分应用它们。

我想应用这个原则来获得加权平均值(除了简单的计数和平均值)。 我的输入表是

import pandas as pd

t = pd.DataFrame({'bucket':['a', 'a', 'b', 'b', 'b'], 'weight': [2, 3, 1, 4, 3], 
                  'qty': [100, 500, 200, 800, 700]})

我的查询失败:

import functools
import numpy as np

t.groupby('bucket').agg(
        NR= ('bucket', 'count'),
        AVG_QTY= ('qty', np.mean),
        W_AVG_QTY= ('qty', functools.partial(np.average, weights='weight'))
   )

带有错误消息:

TypeError: 1D weights expected when shapes of a and weights differ.

我认为问题来自于将参数固定为另一列而不是常量?如果没有使用 apply 和返回 Series 的 lambda 表达式的解决方法,我该如何完成这项工作?

【问题讨论】:

  • IIUC,您需要将group['weight'] 传递给np.average,而不是字符串。
  • 究竟如何?你能提供确切的语法吗?
  • 问题是 GroupBy.agg 作用于单个列,但是加权平均需要 2 个单独的列;一个用于值,另一个用于权重。在这种情况下,GroupBy.apply 是必需的,因为您可以传递 DataFrame。

标签: python pandas group-by functools


【解决方案1】:

加权平均需要 2 个单独的系列(即一个 DataFrame)。因此,GroupBy.apply 是正确的聚合方法。使用pd.concat 加入结果。

pd.concat([t.groupby('bucket').agg(NR = ('bucket', 'count'),
                                   AVG_QTY = ('qty', np.mean)),
           (t.groupby('bucket').apply(lambda gp: np.average(gp.qty, weights=gp.weight))
             .rename('W_AVG_QTY'))], 
          axis=1)

#        NR     AVG_QTY  W_AVG_QTY
#bucket                           
#a        2  300.000000      340.0
#b        3  566.666667      687.5

可以agg 完成,假设你的DataFrame 有一个唯一的索引,但我不能保证考虑到所有的切片它会非常高效。我们创建自己的函数来接受 Series 值和整个 DataFrame。然后该函数使用系列对DataFrame 进行子集化以获得每个组的权重。

def my_w_avg(s, df, wcol):
    return np.average(s, weights=df.loc[s.index, wcol])

t.groupby('bucket').agg(
        NR= ('bucket', 'count'),
        AVG_QTY= ('qty', np.mean),
        W_AVG_QTY= ('qty', functools.partial(my_w_avg, df=t, wcol='weight'))
   )

#        NR     AVG_QTY  W_AVG_QTY
#bucket                           
#a        2  300.000000      340.0
#b        3  566.666667      687.5

【讨论】:

  • 谢谢!我同意,这个解决方案很好地证明了您可以functools.partial 与 GroupBy.agg 一起使用来计算加权平均值,它还证明了您不应该这样做; )
猜你喜欢
  • 1970-01-01
  • 2016-02-15
  • 1970-01-01
  • 1970-01-01
  • 2012-10-11
  • 2021-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多