我有一个这样的数据框:
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
每个id
都有几个与之关联的最大值和最小值。我的期望输出如下所示:
max min
id
1 3 10
2 20 -10
它包含每个max_val
的最大min_val
和最小id
。
目前我按如下方式实施:
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']
我不喜欢的是,我必须在分组数据框.max()
上拨打.min()
和gdf
,我会分别丢弃50%的信息(因为我是对最大min_val
和最小min_val
不感兴趣。
有没有办法以更直接的方式做到这一点,例如:将应该应用于组的函数直接传递给groupby
调用?
编辑:
df.groupby('id')['value'].agg(['max','min'])
是不够的,因为可能存在一个组的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
上述代码的结果:
max min
id
1 3 10
2 20 -10
答案 0 :(得分: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
这将应用一个函数,该函数从组密钥中获取要应用的实数函数的名称。
显然,如果字符串" 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()
请注意,这比上面的版本效率稍低,因为它调用普通的Python max / min而不是优化的pandas版本。但是如果你想要一个更通用的解决方案,那就是你必须做的事情,因为没有优化所有的pandas版本。 (这也或多或少地为什么没有内置的方法来做到这一点:对于大多数数据,你不能假设你的值可以映射到有意义的函数,所以它没有&#39 ; t有意义尝试根据值本身确定要应用的函数。)
答案 1 :(得分:3)
一个选项是使用Place.select(:city, :updated_at).in_state("IL").group(:city, :updated_at).order(:city).distinct
进行自定义聚合,因为它不适合内置聚合方案:
groupby.apply
答案 2 :(得分:2)
pivot_table
的解决方案:
df1 = df.pivot_table(index='id', columns='min_max', values='value', aggfunc=[np.min,np.max])
df1 = df1.loc[:, [('amin','min_val'), ('amax','max_val')]]
df1.columns = df1.columns.droplevel(1)
print (df1)
amin amax
id
1 10 3
2 -10 20