如何将不同的函数应用于groupby对象?

Cle*_*leb 3 python group-by dataframe pandas

我有这样的数据帧:

import pandas as pd

df = pd.DataFrame({'id': [1, 2, 1, 1, 2, 1, 2, 2],
               'min_max': ['max_val', 'max_val', 'min_val', 'min_val', 'max_val', 'max_val', 'min_val', 'min_val'],
               'value': [1, 20, 20, 10, 12, 3, -10, -5 ]})

   id  min_max  value
0   1  max_val      1
1   2  max_val     20
2   1  min_val     20
3   1  min_val     10
4   2  max_val     12
5   1  max_val      3
6   2  min_val    -10
7   2  min_val     -5
Run Code Online (Sandbox Code Playgroud)

每个id都有几个与之相关的最大值和最小值.我想要的输出如下:

    max  min
id          
1     3   10
2    20  -10
Run Code Online (Sandbox Code Playgroud)

它包含每个的最大值max_val和最小值.min_valid

目前我实现如下:

gdf = df.groupby(by=['id', 'min_max'])['value']

max_max = gdf.max().loc[:, 'max_val']
min_min = gdf.min().loc[:, 'min_val']

final_df = pd.concat([max_max, min_min], axis=1)
final_df.columns = ['max', 'min']
Run Code Online (Sandbox Code Playgroud)

我不喜欢的是,我必须打电话.max().min()分组数据gdf框,分别在哪里丢弃50%的信息(因为我对最大min_val和最小的不感兴趣min_val).

有没有办法以更简单的方式执行此操作,例如将应该应用于组的函数直接传递给groupby调用?

编辑:

df.groupby('id')['value'].agg(['max','min'])
Run Code Online (Sandbox Code Playgroud)

是不够的,因为可能存在一个组具有min_val高于max_val该组的全部或max_val低于全部的组的情况min_val.因此,还必须基于该列进行分组min_max.

结果

df.groupby('id')['value'].agg(['max','min'])

    max  min
id          
1    20    1
2    20  -10
Run Code Online (Sandbox Code Playgroud)

上面代码的结果:

    max  min
id          
1     3   10
2    20  -10
Run Code Online (Sandbox Code Playgroud)

Bre*_*arn 6

这是一个略显诙谐的解决方案:

>>> df.groupby(['id', 'min_max'])['value'].apply(lambda g: getattr(g, g.name[1][:3])()).unstack()
min_max  max_val  min_val
id                       
1              3       10
2             20      -10
Run Code Online (Sandbox Code Playgroud)

这将应用一个函数,该函数从组密钥中获取要应用的实函数的名称.

显然,如果字符串"max_val"和函数名"max"之间没有这么简单的关系,这就不会那么简单.它可以通过将dict映射列值映射到要应用的函数来推广,如下所示:

func_map = {'min_val': min, 'max_val': max}
df.groupby(['id', 'min_max'])['value'].apply(lambda g: func_map[g.name[1]](g)).unstack()
Run Code Online (Sandbox Code Playgroud)

请注意,这比上面的版本效率稍低,因为它调用普通的Python max/min而不是优化的pandas版本.但是如果你想要一个更通用的解决方案,那就是你必须要做的事情,因为没有优化的pandas版本.(这也或多或少地为什么没有内置的方法来执行此操作:对于大多数数据,您不能假设您的值可以映射到有意义的函数,因此尝试确定没有意义基于值本身应用的函数.)