dplyr通过多种功能汇总/汇总的熊猫等效于什么?

发布于 2021-01-29 15:11:08

我遇到了从R转换为Panda的问题,该dplyr软件包可以轻松地分组并执行多次汇总。

请帮助改进我现有的Python pandas代码以进行多种聚合:

import pandas as pd
data = pd.DataFrame(
    {'col1':[1,1,1,1,1,2,2,2,2,2],
    'col2':[1,2,3,4,5,6,7,8,9,0],
     'col3':[-1,-2,-3,-4,-5,-6,-7,-8,-9,0]
    }
)
result = []
for k,v in data.groupby('col1'):
    result.append([k, max(v['col2']), min(v['col3'])])
print pd.DataFrame(result, columns=['col1', 'col2_agg', 'col3_agg'])

问题:

  • 太冗长
  • 可能可以优化和高效。(我将for-loop groupby实现重写到其中groupby.agg,并且性能增强非常明显)。

在R中,等效代码为:

data %>% groupby(col1) %>% summarize(col2_agg=max(col2), col3_agg=min(col3))

更新:@ayhan解决了我的问题,这是一个后续问题,我将在此处而不是作为评论发布:

Q2)groupby().summarize(newcolumn=max(col2 * col3))当函数是2+列的复合函数时,即聚合/汇总的等效项是什么?

关注者
0
被浏览
52
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    相当于

    df %>% groupby(col1) %>% summarize(col2_agg=max(col2), col3_agg=min(col3))
    

    df.groupby('col1').agg({'col2': 'max', 'col3': 'min'})
    

    哪个返回

          col2  col3
    col1            
    1        5    -5
    2        9    -9
    

    返回的对象是pandas.DataFrame,其索引名为col1,列名为col2col3。默认情况下,对数据熊猫进行分组时,会将分组列设置为索引,以进行有效的访问和修改。但是,如果您不希望这样做,可以使用两种方法将其设置col1为列。

    • 通过as_index=False

      df.groupby('col1', as_index=False).agg({'col2': 'max', 'col3': 'min'})
      
    • 致电reset_index

      df.groupby('col1').agg({'col2': 'max', 'col3': 'min'}).reset_index()
      

    既屈服

    col1  col2  col3           
       1     5    -5
       2     9    -9
    

    您还可以将多个函数传递给groupby.agg

    agg_df = df.groupby('col1').agg({'col2': ['max', 'min', 'std'], 
                                     'col3': ['size', 'std', 'mean', 'max']})
    

    这也返回一个DataFrame,但现在它具有用于列的MultiIndex。

         col2               col3                   
          max min       std size       std mean max
    col1                                           
    1       5   1  1.581139    5  1.581139   -3  -1
    2       9   0  3.535534    5  3.535534   -6   0
    

    MultiIndex对于选择和分组非常方便。这里有些例子:

    agg_df['col2']  # select the second column
          max  min       std
    col1                    
    1       5    1  1.581139
    2       9    0  3.535534
    
    agg_df[('col2', 'max')]  # select the maximum of the second column
    Out: 
    col1
    1    5
    2    9
    Name: (col2, max), dtype: int64
    
    agg_df.xs('max', axis=1, level=1)  # select the maximum of all columns
    Out: 
          col2  col3
    col1            
    1        5    -1
    2        9     0
    

    较早(版本0.20.0之前),可以使用字典重命名agg调用中的列。例如

    df.groupby('col1')['col2'].agg({'max_col2': 'max'})
    

    将返回第二列的最大值为max_col2

          max_col2
    col1          
    1            5
    2            9
    

    但是,不建议使用改名方法:

    df.groupby('col1')['col2'].agg(['max']).rename(columns={'max': 'col2_max'})
    
          col2_max
    col1          
    1            5
    2            9
    

    对于agg_df上面定义的DataFrame,它可能会很冗长。在这种情况下,可以使用重命名功能来平整这些级别:

    agg_df.columns = ['_'.join(col) for col in agg_df.columns]
    
          col2_max  col2_min  col2_std  col3_size  col3_std  col3_mean  col3_max
    col1                                                                        
    1            5         1  1.581139          5  1.581139         -3        -1
    2            9         0  3.535534          5  3.535534         -6         0
    

    对于类似的操作groupby().summarize(newcolumn=max(col2 * col3)),您仍然可以通过先用添加新列来使用agg
    assign

    df.assign(new_col=df.eval('col2 * col3')).groupby('col1').agg('max')
    
          col2  col3  new_col
    col1                     
    1        5    -1       -1
    2        9     0        0
    

    这将为新旧列返回最大值,但一如既往,您可以对其进行切片。

    df.assign(new_col=df.eval('col2 * col3')).groupby('col1')['new_col'].agg('max')
    
    col1
    1   -1
    2    0
    Name: new_col, dtype: int64
    

    有了groupby.apply这将是更短:

    df.groupby('col1').apply(lambda x: (x.col2 * x.col3).max())
    
    col1
    1   -1
    2    0
    dtype: int64
    

    但是,groupby.apply将此视为自定义函数,因此不会被向量化。到目前为止,我们传递给的函数agg(“ min”,“ max”,“
    min”,“
    size”等)已向量化,这些是这些优化函数的别名。您可以df.groupby('col1').agg('min')用或替换df.groupby('col1').agg(min),它们将全部执行相同的功能。使用自定义功能时,您不会看到相同的效率。df.groupby('col1').agg(np.min)``df.groupby('col1').min()

    最后,从0.20版开始,agg可以直接在DataFrames上使用,而不必先进行分组。在这里查看示例。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看