Python 通过GroupBy.agg和命名聚合计算加权平均值

Python 通过GroupBy.agg和命名聚合计算加权平均值,python,pandas,group-by,functools,Python,Pandas,Group By,Functools,熊猫版本0.25支持通过函数agg和namedtuples进行“命名聚合”。您需要按说明传递列、聚合器对。它还说: 如果聚合函数需要其他参数,请使用functools.partial()部分应用它们 我想应用这个原理得到一个加权平均值(除了一个简单的计数和平均值)。 我的输入表是 将熊猫作为pd导入 t=pd.DataFrame({'bucket':['a','a','b','b'],'weight':[2,3,1,4,3], “数量”:[100500200800700]}) 我的查询失败:

熊猫版本0.25支持通过函数
agg
namedtuples
进行“命名聚合”。您需要按说明传递列、聚合器对。它还说:

如果聚合函数需要其他参数,请使用functools.partial()部分应用它们

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

将熊猫作为pd导入
t=pd.DataFrame({'bucket':['a','a','b','b'],'weight':[2,3,1,4,3],
“数量”:[100500200800700]})
我的查询失败:

导入工具
将numpy作为np导入
t、 groupby('bucket').agg(
NR=(‘桶’、‘计数’),
平均数量=(‘数量’,np.平均值),
W_AVG_QTY=('QTY',functools.partial(np.average,weights='weight'))
)
将显示一条错误消息:

TypeError:当a的形状和权重不同时,需要1D权重。

我假设问题来自于将参数固定为另一列而不是常量?如果没有使用
apply
的变通方法和返回
系列的lambda表达式,我如何才能实现这一点

加权平均需要两个独立的序列(即数据帧)。因此,
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
执行,尽管我不能保证在所有切片的情况下,它的性能会非常好。我们创建自己的函数来接受一系列值和整个数据帧。然后,该函数使用序列对数据帧进行子集设置,以获得每组的权重

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

IIUC,您需要将
组['weight']
传递到
np.average
,而不是字符串。具体如何传递?你能提供准确的语法吗?问题是
GroupBy.agg
作用于单个列,但是加权平均需要两个单独的列;一个用于值,另一个用于权重。在这种情况下,需要使用
GroupBy.apply
,因为您可以传递数据帧。谢谢!我同意,这个解决方案很好地证明了您可以将
functools.partial
与GroupBy.agg一起使用来计算加权平均值,它还表明您不应该这样做;)