【发布时间】:2019-05-10 09:47:23
【问题描述】:
假设我们有一张客户和他们的消费表。
import pandas as pd
df = pd.DataFrame({
"Name": ["Alice", "Bob", "Bob", "Charles"],
"Spend": [3, 5, 7, 9]
})
LIMIT = 6
对于每个客户,我们可以使用apply 方法计算他的支出中大于 6 的部分:
df.groupby("Name").apply(
lambda grp: len(grp[grp["Spend"] > LIMIT]) / len(grp)
)
Name
Alice 0.0
Bob 0.5
Charles 1.0
但是,apply 方法is just a loop,如果有很多客户,它会很慢。
问题:有没有更快的方法,大概使用矢量化?
从 0.23.4 版开始,SeriesGroupBy 不支持比较运算符:
(df.groupby("Name") ["Spend"] > LIMIT).mean()
TypeError: '>' not supported between instances of 'SeriesGroupBy' and 'int'
下面的代码导致 Alice 的值为空:
df[df["Spend"] > LIMIT].groupby("Name").size() / df.groupby("Name").size()
Name
Alice NaN
Bob 0.5
Charles 1.0
下面的代码给出了正确的结果,但它要求我们要么修改表格,要么复制一份以避免修改原件。
df["Dummy"] = 1 * (df["Spend"] > LIMIT)
df.groupby("Name") ["Dummy"] .sum() / df.groupby("Name").size()
【问题讨论】:
-
我认为您应该可以使用
groupby+apply。但是,您正在 lambda 函数中执行昂贵的操作。不需要做遮罩,使用它进行过滤,并使用python内置的len来计算可以有多少True。直接对掩码求和即可:df.groupby('Name').Spend.apply(lambda s: (s>LIMIT).sum()/s.size) -
非常感谢您编辑我蹩脚的英语。
标签: python pandas group-by vectorization apply