这些文档展示了如何使用输出列名作为键的dict在一个groupby对象上同时应用多个函数:
In [563]: grouped['D'].agg({'result1' : np.sum,
.....: 'result2' : np.mean})
.....:
Out[563]:
result2 result1
A
bar -0.579846 -1.739537
foo -0.280588 -1.402938
但是,这只对Series groupby对象有效。当一个dict被类似地传递给一个groupby DataFrame时,它期望键是该函数将应用到的列名。
我想做的是将多个函数应用于多个列(但某些列将被多次操作)。此外,* 某些函数将依赖于groupby对象中的其他列 *(如sumif函数)。我目前的解决方案是一列一列地查看,并执行类似于上面代码的操作,对依赖于其他行的函数使用lambda表达式。但这需要很长时间,(我认为迭代groupby对象需要很长时间)。我将不得不改变它,以便在一次运行中迭代整个groupby对象,但我想知道pandas中是否有一种内置的方法可以更干净地做到这一点。
例如,我曾经尝试过
grouped.agg({'C_sum' : lambda x: x['C'].sum(),
'C_std': lambda x: x['C'].std(),
'D_sum' : lambda x: x['D'].sum()},
'D_sumifC3': lambda x: x['D'][x['C'] == 3].sum(), ...)
但正如预期的那样,我得到了一个KeyError(因为如果从DataFrame调用agg
,则键必须是一个列)。
是否有任何内置的方式来做我想做的事情,或者可能会添加此功能,或者我只需要手动迭代groupby?
8条答案
按热度按时间ezykj2lf1#
currently accepted answer的后半部分已经过时,并且有两个弃用。首先,也是最重要的,您不能再将字典的字典传递给
agg
groupby方法。第二,永远不要使用.ix
。如果你想同时处理两个单独的列,我建议使用
apply
方法,它隐式地将DataFrame传递给应用的函数。让我们使用一个类似的dataframe作为一个从上面从列名Map到聚合函数的字典仍然是执行聚合的好方法。
如果你不喜欢这个丑陋的lambda列名称,你可以使用一个普通的函数,并为特殊的
__name__
属性提供一个自定义名称,如下所示:使用
apply
返回Series现在,如果您有多个列需要一起交互,那么您不能使用
agg
,它会隐式地将Series传递给聚合函数。当使用apply
时,整个组作为DataFrame传递给函数。我建议使用一个自定义函数来返回所有聚合的Series。使用系列索引作为新列的标签:
如果你喜欢MultiIndexes,你仍然可以返回一个这样的Series:
au9on6nz2#
对于第一部分,你可以传递一个列名称的字典作为键,传递一个函数列表作为值:
更新1:
由于聚合函数适用于Series,因此对其他列名的引用将丢失。为了解决这个问题,您可以引用完整的 Dataframe 并使用lambda函数中的组索引对其进行索引。
这里有一个hacky workaround:
这里,结果“D”列由求和的“E”值组成。
更新2:
这里有一个方法,我认为将做你要求的一切。首先创建一个自定义的lambda函数。下面,g引用组。当聚合时,g将是一个系列。将
g.index
传递给df.ix[]
,从df中选择当前组。然后我测试列C是否小于0.5。返回的布尔序列被传递给g[]
,它只选择那些满足条件的行。uyto3xhc3#
Pandas >= 0.25.0
,命名聚合由于pandas版本为
0.25.0
或更高版本,我们正在远离基于字典的聚合和重命名,并转向接受tuple
的命名聚合。现在我们可以同时聚合+重命名为一个更有信息的列名:示例:
使用命名聚合应用
GroupBy.agg
:pcww981p4#
作为Ted Petrou的答案的替代方案(主要是美学),我发现我更喜欢稍微紧凑的列表。请不要考虑接受它,它只是一个更详细的评论泰德的答案,加上代码/数据。Python/pandas不是我的第一个/最好的,但我发现这很好读:
我发现它更像是
dplyr
管道和data.table
链式命令。不是说他们更好,只是对我更熟悉。(我当然认识到使用更正式的def
函数进行这些类型的操作的能力,并且对于许多人来说,这是首选。这只是一种替代,不一定更好)我以和Ted相同的方式生成数据,我将添加一个可重复性的种子。
vpfxa7rd5#
版本0.25.0中的新增功能。
为了支持特定于列的聚合并控制输出列名,pandas接受**GroupBy.agg()**中的特殊语法,称为 “named aggregation”,其中
pandas。NamedAgg只是一个命名元组。也允许使用普通元组。
其他关键字参数不会传递给聚合函数。只有成对的(column,aggfunc)应该作为**kwargs传递。如果您的聚合函数需要额外的参数,请使用functools.partial()部分地应用它们。
命名聚合对于Series groupby聚合也有效。在这种情况下,没有列选择,因此值只是函数。
8oomwypt6#
这是对使用命名聚合的“exans”答案的扭曲。这是相同的,但与参数解包,这允许你仍然在一个字典传递给agg函数。
命名的aggs是一个很好的特性,但是乍一看似乎很难以编程方式编写,因为它们使用了关键字,但是实际上使用参数/关键字解包很简单。
结果
uqxowvwt7#
泰德的回答令人惊讶。最后我用了一个更小的版本,以防有人感兴趣。在查找依赖于多个列中的值的一个聚合时非常有用:
创建数据框
使用apply进行分组和聚合(使用多列)
使用aggregate进行分组和聚合(使用多列)
我喜欢这种方法,因为我仍然可以使用聚合。也许人们会告诉我为什么在对组进行聚合时需要apply来获取多个列。
现在看起来很明显,但是只要你不直接在groupby* 之后选择感兴趣的列 *,你就可以从聚合函数中访问所有的列。
只能访问所选列
访问所有列,因为选择是所有魔术之后
或类似
我希望这能帮上忙。
k5ifujac8#
和
不起作用。抛出键错误:“KeyError:'a'”
这一个工作(@r2evans的回答):