使用带有参数的 Pandas groupby() + apply()

Posted

技术标签:

【中文标题】使用带有参数的 Pandas groupby() + apply()【英文标题】:Use Pandas groupby() + apply() with arguments 【发布时间】:2017-09-14 22:52:49 【问题描述】:

我想将df.groupby()apply() 结合使用,将函数应用于每个组的每一行。

我通常使用以下代码,它通常可以工作(注意,这是没有groupby()):

df.apply(myFunction, args=(arg1,))

使用groupby(),我尝试了以下方法:

df.groupby('columnName').apply(myFunction, args=(arg1,))

但是,我收到以下错误:

TypeError: myFunction() 得到了一个意外的关键字参数 'args'

因此,我的问题是:如何将groupby()apply() 与需要参数的函数一起使用?

【问题讨论】:

这适用于df.groupby('columnName').apply(myFunction, ('arg1')) @Zero 这是一个很好的答案,因为它与 OP 尝试的解决方案非常相似,并且不需要 lambda。我建议您将其发布为答案。 @Zero,我和 OP 有同样的问题,但这对我不起作用——我仍然得到与 OP 相同的错误。另外,我可以问一下为什么您的评论应该有效,为什么 OP 的方法(与我的方法相同)无效?我没有发现它在任何地方都有记录 尝试.apply(myFunction, args = ('arg1',) 注意,arg1之后。 其实我自己试了下也没用... 【参考方案1】:

pandas.core.groupby.GroupBy.apply 没有named 参数args,但pandas.DataFrame.apply 有。

所以试试这个:

df.groupby('columnName').apply(lambda x: myFunction(x, arg1))

或按照@Zero的建议:

df.groupby('columnName').apply(myFunction, ('arg1'))

演示:

In [82]: df = pd.DataFrame(np.random.randint(5,size=(5,3)), columns=list('abc'))

In [83]: df
Out[83]:
   a  b  c
0  0  3  1
1  0  3  4
2  3  0  4
3  4  2  3
4  3  4  1

In [84]: def f(ser, n):
    ...:     return ser.max() * n
    ...:

In [85]: df.apply(f, args=(10,))
Out[85]:
a    40
b    40
c    40
dtype: int64

当使用GroupBy.apply 时,您可以传递一个命名参数:

In [86]: df.groupby('a').apply(f, n=10)
Out[86]:
    a   b   c
a
0   0  30  40
3  30  40  40
4  40  20  30

参数元组:

In [87]: df.groupby('a').apply(f, (10))
Out[87]:
    a   b   c
a
0   0  30  40
3  30  40  40
4  40  20  30

【讨论】:

你确定没有办法在元组中传递args 参数吗?我在其他地方看到过在 .apply 上使用它,它消除了对 lambda 表达式的需要。 @BradSolomon 在问题 cmets 中看到 Zero 的答案 为什么这行得通,而 OP 所做的却没有?我没有关注,我在任何地方都找不到它的记录。 @Pythonistaan​​onymous,现在您甚至有两个答案可以回答您的问题:-D @MehdiAbbassi,试试这个:df.groupby('columnName').apply(lambda x: myFunction(x, x.shift(-1)) ;)【参考方案2】:

关于为什么使用args 参数会引发错误的一些困惑可能源于pandas.DataFrame.apply 确实有一个args 参数(一个元组),而pandas.core.groupby.GroupBy.apply 没有。

所以,当你在 DataFrame 本身上调用 .apply 时,你可以使用这个参数;当你在 groupby 对象上调用 .apply 时,你不能。

在@MaxU 的回答中,表达式lambda x: myFunction(x, arg1) 被传递给func(第一个参数);不需要额外指定*args/**kwargs,因为arg1是在lambda中指定的。

一个例子:

import numpy as np
import pandas as pd

# Called on DataFrame - `args` is a 1-tuple
# `0` / `1` are just the axis arguments to np.sum
df.apply(np.sum, axis=0)  # equiv to df.sum(0)
df.apply(np.sum, axis=1)  # equiv to df.sum(1)


# Called on groupby object of the DataFrame - will throw TypeError
print(df.groupby('col1').apply(np.sum, args=(0,)))
# TypeError: sum() got an unexpected keyword argument 'args'

【讨论】:

【参考方案3】:

对我来说

df2 = df.groupby('columnName').apply(lambda x: my_function(x, arg1, arg2,))

工作

【讨论】:

以上是关于使用带有参数的 Pandas groupby() + apply()的主要内容,如果未能解决你的问题,请参考以下文章

带有分隔符的 Pandas groupby 连接

带有最小值、最大值和总和的 Pandas 数据框 Groupby

带有冗余 nan 类别的 Pandas groupby

带有 bin 计数的 Pandas groupby

带有 pandas、groupby、子图、计算/描述性统计、聚合的箱线图

Python Pandas - 带有 apply() 和 rolling() 的 groupby() 非常慢