B.M*_*.W. 32 python r pandas summarize pandas-groupby
我曾经和R一起工作,真的很喜欢你可以轻松分组并总结的dplyr软件包.
但是,在pandas中,我没有看到相当的总结,这是我在Python中实现它的方式:
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'])
Run Code Online (Sandbox Code Playgroud)
它不仅非常冗长,而且可能不是最优化和最有效的.(我曾经重写过一个dplyr实现for-loop groupby,性能提升很大).
在R中代码将是
data %>% groupby(col1) %>% summarize(col2_agg=max(col2), col3_agg=min(col3))
Run Code Online (Sandbox Code Playgroud)
在Python或for循环中是否有一个有效的等价物是我必须使用的.
另外,@ ahan真的给了我答案的解决方案,这是一个后续问题,我将在这里列出而不是评论:
什么是相当于 groupby.agg
ayh*_*han 50
相当于
df %>% groupby(col1) %>% summarize(col2_agg=max(col2), col3_agg=min(col3))
Run Code Online (Sandbox Code Playgroud)
是
df.groupby('col1').agg({'col2': 'max', 'col3': 'min'})
Run Code Online (Sandbox Code Playgroud)
返回
col2 col3
col1
1 5 -5
2 9 -9
Run Code Online (Sandbox Code Playgroud)
返回的对象是一个名为索引的pandas.DataFrame col1和命名的列col2和col3.默认情况下,对数据进行分组时,pandas会将分组列设置为有效访问和修改的索引.但是,如果您不希望这样,则有两种方法可以设置col1为列.
通过as_index=False:
df.groupby('col1', as_index=False).agg({'col2': 'max', 'col3': 'min'})
Run Code Online (Sandbox Code Playgroud)致电reset_index:
df.groupby('col1').agg({'col2': 'max', 'col3': 'min'}).reset_index()
Run Code Online (Sandbox Code Playgroud)都屈服了
col1 col2 col3
1 5 -5
2 9 -9
Run Code Online (Sandbox Code Playgroud)
您还可以传递多个功能groupby.agg.
agg_df = df.groupby('col1').agg({'col2': ['max', 'min', 'std'],
'col3': ['size', 'std', 'mean', 'max']})
Run Code Online (Sandbox Code Playgroud)
这也返回一个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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
早些时候(版本0.20.0之前)可以使用字典重命名agg调用中的列.例如
df.groupby('col1')['col2'].agg({'max_col2': 'max'})
Run Code Online (Sandbox Code Playgroud)
将返回第二列的最大值max_col2:
max_col2
col1
1 5
2 9
Run Code Online (Sandbox Code Playgroud)
但是,它被弃用以支持重命名方法:
df.groupby('col1')['col2'].agg(['max']).rename(columns={'max': 'col2_max'})
col2_max
col1
1 5
2 9
Run Code Online (Sandbox Code Playgroud)
对于像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
Run Code Online (Sandbox Code Playgroud)
对于类似的操作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
Run Code Online (Sandbox Code Playgroud)
这将返回旧列和新列的最大值,但与往常一样,您可以对其进行切片.
df.assign(new_col=df.eval('col2 * col3')).groupby('col1')['new_col'].agg('max')
col1
1 -1
2 0
Name: new_col, dtype: int64
Run Code Online (Sandbox Code Playgroud)
有了groupby.apply这将是更短:
df.groupby('col1').apply(lambda x: (x.col2 * x.col3).max())
col1
1 -1
2 0
dtype: int64
Run Code Online (Sandbox Code Playgroud)
但是,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可以直接在DataFrame上使用,而无需先进行分组.见这里的例子.
使用以下方法可以很容易地将 R 代码转换为 python 代码,而无需学习 pandas 的 API datar:
>>> 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
Run Code Online (Sandbox Code Playgroud)
我是该包的作者。如果您有任何疑问,请随时提交问题。