【问题标题】:How do you change input parameters of pandas groupby.agg function?如何更改 pandas groupby.agg 函数的输入参数?
【发布时间】:2021-05-10 02:30:34
【问题描述】:

我在使用 groupby_object.agg() 方法和要更改输入参数的函数时遇到问题。是否有可用的函数名称 .agg() 接受的资源,以及如何将参数传递给它们?

请看下面的例子:

import pandas as pd
import numpy as np

df = pd.DataFrame({'numbers': [1, 2, 3, 2, 1, 3], 
               'colors': ['red', 'white', 'blue', 'red', 'white', np.nan], 
               'weight': [10, 10, 20, 5, 10, 20]})

df['colors'].nunique() # Returns 3 as NaN is not counted
df['colors'].nunique(dropna=False) # Returns 4 as NaN is counted

当我然后 groupby 'colors' 时,如何将 dropna=False 参数与函数一起传递?

df.groupby('numbers').agg({'colors': 'nunique', 'weight': 'sum'})

【问题讨论】:

    标签: python pandas pandas-groupby


    【解决方案1】:

    虽然pandas 有很好的语法来与dicts 和NamedAggs 进行聚合,但这些可能会带来巨大的效率成本。原因是因为没有使用在 cython 中优化和/或实现的内置 groupby 方法,任何 .agg(lambda x: ...).apply(lambda x: ...) 都将采用慢得多的路径。

    这意味着您应该坚持使用可以直接引用或通过别名引用的内置函数。只有在万不得已的情况下,您才应该尝试使用lambda

    在这种特殊情况下使用

    df.groupby('numbers')[['colors']].agg('nunique', dropna=False)
    

    避免

    df.groupby('numbers').agg({'colors': lambda x: x.nunique(dropna=False)})
    

    这个例子表明,虽然输出相同,并且看似很小的变化,但在性能方面会产生巨大的影响,尤其是当组的数量变大时。

    import perfplot
    import pandas as pd
    import numpy as np
    
    def built_in(df):
        return df.groupby('numbers')[['colors']].agg('nunique', dropna=False)
    
    def apply(df):
        return df.groupby('numbers').agg({'colors': lambda x: x.nunique(dropna=False)})
    
    perfplot.show(
        setup=lambda n: pd.DataFrame({'numbers': np.random.randint(0, n//10+1, n),
                                      'colors': np.random.choice([np.NaN] + [*range(100)])}),
        kernels=[
            lambda df: built_in(df),
            lambda df: apply(df)],
        
        labels=['Built-In', 'Apply'],
        n_range=[2 ** k for k in range(1, 20)],
        equality_check=np.allclose,  
        xlabel='~N Groups'
    )
    


    但是你想做多个聚合并使用不同的列

    groupby 的.groupby() 部分并没有真正做那么多;它只是确保映射是正确的。因此,虽然不直观,但与使用 lambda 的更简单的 dict 进行聚合相比,单独与内置聚合并最终连接结果仍然要快得多。

    这是一个同样想sum权重列的例子,我们可以看到拆分仍然快很多,尽管需要手动加入

    def built_in(df):
        return pd.concat([df.groupby('numbers')[['colors']].agg('nunique', dropna=False),
                          df.groupby('numbers')[['weight']].sum()], axis=1)
    
    def apply(df):
        return df.groupby('numbers').agg({'colors': lambda x: x.nunique(dropna=False), 
                                          'weight': 'sum'})
    
    perfplot.show(
        setup=lambda n: pd.DataFrame({'numbers': np.random.randint(0, n//10+1, n),
                                      'colors': np.random.choice([np.NaN] + [*range(100)]),
                                      'weight': np.random.normal(0,1,n)}),
        kernels=[
            lambda df: built_in(df),
            lambda df: apply(df)],
        
        labels=['Built-In', 'Apply'],
        n_range=[2 ** k for k in range(1, 20)],
        equality_check=np.allclose,  
        xlabel='~N Groups'
    )
    

    【讨论】:

    • 这是一个很好的解释,谢谢。根据您的回答提出问题,df.groupby('numbers')[['colors']].agg('nunique', dropna=False) 这意味着聚合的唯一列将是colors,我可以更改为df.groupby('numbers')[['colors','weight']].agg('nunique', dropna=False) 以获得两列的唯一列表。但是,如果有人想在重量列上获得max(),在颜色列上获得nunique,该怎么办?
    • @sophods 啊,是的,对不起,我只是添加了那个。您可以查看我的第二个示例,其中我拆分了一个 groupby,最后拆分为 concat。如果效率不是一个大问题(即,也许你有一个小的 df,而不是一个有 2000 万组的),那么我会说可读性可能更重要。但在许多数据较大的情况下,这些减速可能是 1 分钟或 1 小时计算之间的差异,因此采用稍微复杂一点的编码路径通常会更好。
    【解决方案2】:

    您可以使用此链接 https://pandas.pydata.org/pandas-docs/stable/user_guide/groupby.html

    并导航到“聚合”部分,您可以在其中找到可用于分组数据的不同方法。

    在您的情况下,如果您使用 lambda 函数,则可以传递 dropna=False

    df.groupby('numbers').agg({'colors': lambda x: x.nunique(dropna=False), 'weight': 'sum'})
    
    Out[324]: 
             colors  weight
    numbers                
    1             2      20
    2             2      15
    3             2      40
    

    【讨论】:

      猜你喜欢
      • 2019-08-11
      • 2021-02-22
      • 2022-10-04
      • 1970-01-01
      • 2015-03-28
      • 2018-08-10
      • 2018-07-28
      • 1970-01-01
      • 2012-04-04
      相关资源
      最近更新 更多