使用 pandas GroupBy.agg() 对同一列进行多次聚合

2024-12-05 08:37:00
admin
原创
151
摘要:问题描述:是否有一种内置的 pandas 方法可以将两个不同的聚合函数应用于f1, f2同一列df["returns"],而无需agg()多次调用?示例数据框:import pandas as pd import datetime as dt import numpy as np pd....

问题描述:

是否有一种内置的 pandas 方法可以将两个不同的聚合函数应用于f1, f2同一列df["returns"],而无需agg()多次调用?

示例数据框:

import pandas as pd
import datetime as dt
import numpy as np

pd.np.random.seed(0)
df = pd.DataFrame({
         "date"    :  [dt.date(2012, x, 1) for x in range(1, 11)], 
         "returns" :  0.05 * np.random.randn(10), 
         "dummy"   :  np.repeat(1, 10)
}) 

从语法上讲是错误的,但直观上是正确的,做法是:

# Assume `f1` and `f2` are defined for aggregating.
df.groupby("dummy").agg({"returns": f1, "returns": f2})

显然,Python 不允许重复的键。还有其他方式来表达输入吗agg()?也许元组列表[(column, function)]会更好,以允许将多个函数应用于同一列?但agg()似乎它只接受字典。

除了定义一个仅应用其中两个函数的辅助函数之外,还有其他解决方法吗?(无论如何,这与聚合如何一起工作?)


解决方案 1:

截至 2022-06-20,以下是公认的聚合做法:

df.groupby('dummy').agg(
    Mean=('returns', np.mean),
    Sum=('returns', np.sum))

请参阅此答案以了解更多信息。


折叠下方包含 的历史版本pandas

您可以简单地将函数作为列表传递:

In [20]: df.groupby("dummy").agg({"returns": [np.mean, np.sum]})
Out[20]:         
           mean       sum
dummy                    
1      0.036901  0.369012

或者作为字典:

In [21]: df.groupby('dummy').agg({'returns':
                                  {'Mean': np.mean, 'Sum': np.sum}})
Out[21]: 
        returns          
           Mean       Sum
dummy                    
1      0.036901  0.369012

解决方案 2:

TLDR;Pandasgroupby.agg有一个新的、更简单的语法,用于指定 (1) 多列上的聚合,以及 (2) 单列上的多个聚合。因此,要对pandas >= 0.25执行此操作,请使用

df.groupby('dummy').agg(Mean=('returns', 'mean'), Sum=('returns', 'sum'))

           Mean       Sum
dummy                    
1      0.036901  0.369012

或者

df.groupby('dummy')['returns'].agg(Mean='mean', Sum='sum')

           Mean       Sum
dummy                    
1      0.036901  0.369012

Pandas >= 0.25:命名聚合

Pandas 已改变其行为,GroupBy.agg转而采用更直观的语法来指定命名聚合。请参阅0.25 文档中的增强功能部分以及相关的 GitHub 问题GH18366和GH26512。

根据文档,

为了支持特定于列的聚合并控制输出列名称,pandas 接受 中的特殊语法GroupBy.agg(),称为“命名聚合”,其中

  • 关键字是输出列名称

  • 这些值是元组,其第一个元素是要选择的列,第二个元素是要应用于该列的聚合。Pandas 提供了带有字段 ['column', 'aggfunc'] 的 pandas.NamedAgg 命名元组,以使参数更清晰。与往常一样,聚合可以是可调用的或字符串别名。

现在,您可以通过关键字参数传递元组。元组遵循以下格式(<colName>, <aggFunc>)

import pandas as pd

pd.__version__                                                                                                                            
# '0.25.0.dev0+840.g989f912ee'

# Setup
df = pd.DataFrame({'kind': ['cat', 'dog', 'cat', 'dog'],
                   'height': [9.1, 6.0, 9.5, 34.0],
                   'weight': [7.9, 7.5, 9.9, 198.0]
})

df.groupby('kind').agg(
    max_height=('height', 'max'), min_weight=('weight', 'min'),)

      max_height  min_weight
kind                        
cat          9.5         7.9
dog         34.0         7.5

或者,您可以使用pd.NamedAgg(本质上是一个命名元组),它使事情变得更加明确。

df.groupby('kind').agg(
    max_height=pd.NamedAgg(column='height', aggfunc='max'), 
    min_weight=pd.NamedAgg(column='weight', aggfunc='min')
)

      max_height  min_weight
kind                        
cat          9.5         7.9
dog         34.0         7.5

对于 Series 来说甚至更简单,只需将 aggfunc 传递给关键字参数。

df.groupby('kind')['height'].agg(max_height='max', min_height='min')    

      max_height  min_height
kind                        
cat          9.5         9.1
dog         34.0         6.0       

最后,如果您的列名不是有效的 Python 标识符,请使用解包的字典:

df.groupby('kind')['height'].agg(**{'max height': 'max', ...})

熊猫 < 0.25

在较新版本的 pandas 0.24 中,如果使用字典来指定聚合输出的列名,则会得到FutureWarning

df.groupby('dummy').agg({'returns': {'Mean': 'mean', 'Sum': 'sum'}})
# FutureWarning: using a dict with renaming is deprecated and will be removed 
# in a future version

在 v0.20 中,使用字典重命名列已弃用。在较新版本的 pandas 中,可以通过传递元组列表更简单地指定此操作。如果以这种方式指定函数,则该列的所有函数都需要指定为 (name, function) 对的元组。

df.groupby("dummy").agg({'returns': [('op1', 'sum'), ('op2', 'mean')]})

        returns          
            op1       op2
dummy                    
1      0.328953  0.032895

或者,

df.groupby("dummy")['returns'].agg([('op1', 'sum'), ('op2', 'mean')])

            op1       op2
dummy                    
1      0.328953  0.032895

解决方案 3:

类似这样的工作会成功吗:

In [7]: df.groupby('dummy').returns.agg({'func1' : lambda x: x.sum(), 'func2' : lambda x: x.prod()})
Out[7]: 
              func2     func1
dummy                        
1     -4.263768e-16 -0.188565

解决方案 4:

如果您有多个列需要应用相同的多个聚合函数,最简单的方法(imo)是使用字典理解。

#setup
df = pd.DataFrame({'dummy': [0, 1, 1], 'A': range(3), 'B':range(1, 4), 'C':range(2, 5)})

# aggregation
df.groupby("dummy").agg({k: ['sum', 'mean'] for k in ['A', 'B', 'C']})

多索引

以上结果生成一个具有 MultiIndex 列的数据框。如果需要平面自定义列名称,则可以使用命名聚合(如此处其他答案所建议的那样)。

如文档中所述,键应为输出列名,值应(column, aggregation function)为命名聚合的元组。由于存在多个列和多个函数,因此会产生嵌套结构。要将其展平为单个字典,您可以使用collections.ChainMap()或嵌套循环。

此外,如果您更喜欢将石斑鱼列(dummy)作为列(而不是索引),请as_index=False在中指定groupby()

from collections import ChainMap
# convert a list of dictionaries into a dictionary
dct = dict(ChainMap(*reversed([{f'{k}_total': (k, 'sum'), f'{k}_mean': (k, 'mean')} for k in ['A','B','C']])))
# {'A_total': ('A', 'sum'), 'A_avg': ('A', 'mean'), 'B_total': ('B', 'sum'), 'B_avg': ('B', 'mean'), 'C_total': ('C', 'sum'), 'C_avg': ('C', 'mean')}

# the same result obtained by a nested loop
# dct = {k:v for k in ['A','B','C'] for k,v in [(f'{k}_total', (k, 'sum')), (f'{k}_avg', (k, 'mean'))]}

# aggregation
df.groupby('dummy', as_index=False).agg(**dct)

平坦的

解决方案 5:

您还可以在 NamedAggregation 中使用 lambda

df.groupby('dummy').returns.agg({
  'summed' : pd.NamedAgg(column='date', aggfunc=lambda series: sum(series.values()),
  'joined' : pd.NamedAgg(column='returns', aggfunc=lambda series: ','.join(series.values())),
})
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用