【问题标题】:Pandas groupby aggregate to new columnsPandas groupby 聚合到新列
【发布时间】:2017-07-20 23:05:18
【问题描述】:

我有一个看起来像这样的 DataFrame:

A    B    C   D
1    10   22  14
1    12   20  37
1    11   8   18
1    10   10  6
2    11   13  4
2    12   10  12
3    14   0   5

还有一个看起来像这样的函数(注意:它实际上正在做一些更复杂的事情,不能轻易分成三个独立的调用,但为了清楚起见,我正在简化): p>

def myfunc(g):
    return min(g), mean(g), max(g)

我想在A 上使用groupby 和myfunc 以获得B 和C 列上的输出(忽略D),如下所示:

                B               C
   min  mean  max  min  mean  max
A
1  10  10.75  12     8  15.0   22
2  11  11.50  12    10  11.5   13
3  14  14.00  14     0   0.0    0

我可以做到以下几点:

df2.groupby('A')[['B','C']].agg(
    {
        'min':  lambda g: myfunc(g)[0],
        'mean': lambda g: myfunc(g)[1],
        'max':  lambda g: myfunc(g)[2]
    })

但后来——除了这很丑和多次打电话给myfunc——我最终得到了

  max       mean       min
    B   C      B     C   B   C
A
1  12  22  10.75  15.0  10   8
2  12  13  11.50  11.5  11  10
3  14   0  14.00   0.0  14   0

我可以使用.swaplevel(axis=1) 来交换列级别,但即便如此B 和C 在多个重复的列中,并且在调用多个函数时感觉就像在找错树。

【问题讨论】:

    标签: python pandas multi-index


    【解决方案1】:

    如果您安排myfunc 返回一个DataFrame,其列为['A','B','C','D'],其行索引为['min', 'mean', 'max'],那么您可以使用groupby/apply 调用函数(每个组一次)并连接结果根据需要:

    import numpy as np
    import pandas as pd
    
    def myfunc(g):
        result = pd.DataFrame({'min':np.min(g),
                               'mean':np.mean(g),
                               'max':np.max(g)}).T
        return result
    
    df = pd.DataFrame({'A': [1, 1, 1, 1, 2, 2, 3],
     'B': [10, 12, 11, 10, 11, 12, 14],
     'C': [22, 20, 8, 10, 13, 10, 0],
     'D': [14, 37, 18, 6, 4, 12, 5]})
    
    result = df.groupby('A')[['B','C']].apply(myfunc)
    result = result.unstack(level=-1)
    print(result)
    

    打印

          B                  C            
        max   mean   min   max  mean   min
    A                                     
    1  12.0  10.75  10.0  22.0  15.0   8.0
    2  12.0  11.50  11.0  13.0  11.5  10.0
    3  14.0  14.00  14.0   0.0   0.0   0.0
    

    对于可能遇到此问题且不需要自定义函数的其他人,请注意 您应该始终使用builtin aggregators(如下,由 字符串 'min'、'mean' 和 'max') 如果可能的话。他们的表现优于 自定义 Python 函数。令人高兴的是,在这个玩具问题中,它产生了预期的结果:

    In [99]: df.groupby('A')[['B','C']].agg(['min','mean','max'])
    Out[99]: 
        B              C          
      min   mean max min  mean max
    A                             
    1  10  10.75  12   8  15.0  22
    2  11  11.50  12  10  11.5  13
    3  14  14.00  14   0   0.0   0
    

    【讨论】:

      【解决方案2】:

      这样的事情可能会奏效。

      df2.groupby('A')[['B','C']]
      aggregated = df2.agg(['min', 'mean', 'max'])
      

      那么您可以使用交换级别来交换列顺序

      aggregated.columns = aggregated.columns.swaplevel(0, 1)
      aggregated.sortlevel(0, axis=1, inplace=True)
      

      【讨论】:

      • 注意:它实际上是在做一些更复杂的事情,不能轻易分成三个独立的调用,但为了清楚起见,我正在简化
      猜你喜欢
      • 2019-12-22
      • 2021-11-01
      • 2019-10-12
      • 2017-07-02
      • 2017-06-07
      • 2014-11-23
      • 2020-11-05
      • 1970-01-01
      • 2022-01-21
      相关资源
      最近更新 更多