dplyr summarize/aggregate by multiple functions 的 pandas 等价物是什么?

新手上路,请多包涵

我在从 R 转换到 pandas 时遇到问题,其中 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+ 列的复合函数的聚合/汇总?

原文由 B.Mr.W. 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 512
2 个回答

相当于

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 。默认情况下,当您对数据进行分组时,pandas 将分组列设置为索引以进行高效访问和修改。但是,如果您不希望这样,则有两种选择可以将 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)) 类的操作,您仍然可以通过首先使用 assign 添加一个新列来使用 agg。

 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’ 等)是向量化的,这些是那些优化函数的别名。 You can replace df.groupby('col1').agg('min') with df.groupby('col1').agg(min) , df.groupby('col1').agg(np.min) or df.groupby('col1').min() and they will all execute the same function.使用自定义函数时,您将看不到同样的效率。

最后,从 0.20 版开始, agg 可以直接在 DataFrame 上使用,而无需先进行分组。请参阅 此处 的示例。

原文由 ayhan 发布,翻译遵循 CC BY-SA 3.0 许可协议

使用 datar 无需学习 pandas API 就可以很容易地将 R 代码转换为 python 代码:

 >>> from datar import f
>>> from datar.tibble import tibble
>>> from datar.dplyr import group_by, summarize
>>> from datar.base import min, max
>>> data = tibble(
...     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]
... )
>>> data >> group_by(f.col1) >> summarize(col2_agg=max(f.col2), col3_agg=min(f.col3))
   col1  col2_agg  col3_agg
0     1         5        -5
1     2         9        -9

我是包的作者。如果您有任何问题,请随时提交问题。

原文由 Panwen Wang 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题