Fer*_*don 5 python group-by pandas functools
Pandas 0.25 版通过函数agg和namedtuples. 您需要按照文档描述传递列、聚合器对。它还说:
如果您的聚合函数需要额外的参数,请使用 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]})
Run Code Online (Sandbox Code Playgroud)
我的查询失败了:
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'))
)
Run Code Online (Sandbox Code Playgroud)
带有错误消息:
TypeError: 1D weights expected when shapes of a and weights differ.
Run Code Online (Sandbox Code Playgroud)
我认为问题来自将参数固定为另一列而不是常量?如果没有使用的解决方法apply和返回 a 的 lambda 表达式,我怎样才能使这项工作Series?
加权平均值需要 2 个独立的 Series(即 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
Run Code Online (Sandbox Code Playgroud)
假设您的 DataFrame 有一个唯一的索引,这可以通过 来完成agg,尽管我不能保证它在考虑所有切片的情况下会非常高效。我们创建自己的函数来接受一系列值和整个 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
Run Code Online (Sandbox Code Playgroud)