Pandas GroupBy.apply 方法复制第一组
Posted
技术标签:
【中文标题】Pandas GroupBy.apply 方法复制第一组【英文标题】:Pandas GroupBy.apply method duplicates first group 【发布时间】:2014-02-18 19:59:46 【问题描述】:我的第一个 SO 问题: 我对熊猫(0.12.0-4)中 groupby 的应用方法的这种行为感到困惑,它似乎将函数 TWICE 应用于数据帧的第一行。例如:
>>> from pandas import Series, DataFrame
>>> import pandas as pd
>>> df = pd.DataFrame('class': ['A', 'B', 'C'], 'count':[1,0,2])
>>> print(df)
class count
0 A 1
1 B 0
2 C 2
我先检查一下groupby功能是否正常,好像没问题:
>>> for group in df.groupby('class', group_keys = True):
>>> print(group)
('A', class count
0 A 1)
('B', class count
1 B 0)
('C', class count
2 C 2)
然后我尝试在 groupby 对象上使用 apply 做类似的事情,我得到了第一行输出两次:
>>> def checkit(group):
>>> print(group)
>>> df.groupby('class', group_keys = True).apply(checkit)
class count
0 A 1
class count
0 A 1
class count
1 B 0
class count
2 C 2
任何帮助将不胜感激!谢谢。
编辑:@Jeff 在下面提供了答案。本人密密麻麻一下子没看懂,所以这里举个简单的例子来说明,尽管上例中第一组的双打印输出,但是apply方法只对第一组操作一次,不会对原始数据帧进行变异:
>>> def addone(group):
>>> group['count'] += 1
>>> return group
>>> df.groupby('class', group_keys = True).apply(addone)
>>> print(df)
class count
0 A 1
1 B 0
2 C 2
但是通过将方法的返回分配给一个新对象,我们看到它按预期工作:
>>> df2 = df.groupby('class', group_keys = True).apply(addone)
>>> print(df2)
class count
0 A 2
1 B 1
2 C 3
【问题讨论】:
从 v0.25 开始,行为将发生变化,因此第一组只评估一次。 Please see here. 请将接受的答案更新为此answer,因为旧答案不再有效。 【参考方案1】:这是设计使然,如 here 和 here 所述
apply
函数需要知道返回数据的形状,才能智能地确定如何组合。为此,它会调用该函数(在您的情况下为 checkit
)两次以实现此目的。
根据您的实际用例,您可以将调用apply
替换为aggregate
、transform
或filter
,详细描述here。这些函数要求返回值是特定的形状,因此不要调用该函数两次。
但是 - 如果您调用的函数没有副作用,那么函数在第一个值上被调用两次很可能并不重要。
【讨论】:
【参考方案2】:您可以使用 for 循环来避免 groupby.apply 重复第一行,
log_sample.csv
guestid,keyword
1,null
2,null
2,null
3,null
3,null
3,null
4,null
4,null
4,null
4,null
我的代码片段
df=pd.read_csv("log_sample.csv")
grouped = df.groupby("guestid")
for guestid, df_group in grouped:
print(list(df_group['guestid']))
df.head(100)
输出
[1]
[2, 2]
[3, 3, 3]
[4, 4, 4, 4]
【讨论】:
【参考方案3】:这个“问题”现已修复:升级到 0.25+
从 v0.25 开始,GroupBy.apply()
只会评估第一组一次。见GH24748。
What’s new in 0.25.0 (July 18, 2019): Groupby.apply
on DataFrame
evaluates first group only once
文档中的相关示例:
pd.__version__
# '0.25.0.dev0+590.g44d5498d8'
df = pd.DataFrame("a": ["x", "y"], "b": [1, 2])
def func(group):
print(group.name)
return group
新行为 (>=v0.25):
df.groupby('a').apply(func)
x
y
a b
0 x 1
1 y 2
旧行为(
df.groupby('a').apply(func)
x
x
y
a b
0 x 1
1 y 2
Pandas 仍然使用第一组来判断apply
是否可以走快速路径。但至少它不再需要对第一组进行两次评估。干得好,开发者!
【讨论】:
哦,所以基本上 Pandas 仍然会在第一行运行apply
两次。此修复仅适用于 groupby.apply 中的组。该死的。
@CMCDragonkai 现在.apply
也是如此。
哪个版本的熊猫?以上是关于Pandas GroupBy.apply 方法复制第一组的主要内容,如果未能解决你的问题,请参考以下文章
使用带有参数的 Pandas groupby() + apply()
使用 pandas groupby + apply 和 condensing groups 计算平均值的更快方法
groupby+(apply+agg+transform)方法的比较