dplyr通过多种功能汇总/汇总的熊猫等效于什么?
我遇到了从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+列的复合函数时,即聚合/汇总的等效项是什么?
-
相当于
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
,列名为col2
和col3
。默认情况下,对数据熊猫进行分组时,会将分组列设置为索引,以进行有效的访问和修改。但是,如果您不希望这样做,可以使用两种方法将其设置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上使用,而不必先进行分组。在这里查看示例。 -