Pandas groupby 聚合到新列
Pandas groupby aggregate to new columns
我有一个看起来像这样的 DataFrame:
A B C D
1 10 22 14
1 12 20 37
1 11 8 18
1 10 10 6
2 11 13 4
2 12 10 12
3 14 0 5
和一个看起来像这样的函数(注意:它实际上在做一些更复杂的事情,不能轻易分成三个独立的调用,但为了清楚起见,我进行了简化):
def myfunc(g):
return min(g), mean(g), max(g)
我想在 A
上使用 groupby
和 myfunc
以获得列 B
和 C
上的输出(忽略 D
) 像这样:
B C
min mean max min mean max
A
1 10 10.75 12 8 15.0 22
2 11 11.50 12 10 11.5 13
3 14 14.00 14 0 0.0 0
我可以做到以下几点:
df2.groupby('A')[['B','C']].agg(
{
'min': lambda g: myfunc(g)[0],
'mean': lambda g: myfunc(g)[1],
'max': lambda g: myfunc(g)[2]
})
但是——除了这个丑陋和多次调用 myfunc
——我最终得到
max mean min
B C B C B C
A
1 12 22 10.75 15.0 10 8
2 12 13 11.50 11.5 11 10
3 14 0 14.00 0.0 14 0
我可以使用 .swaplevel(axis=1)
来交换列级别,但即使这样 B
和 C
仍然在多个重复的列中,并且通过多个函数调用感觉就像在咆哮错误的树。
如果你安排 myfunc
到 return 列为 ['A','B','C','D']
行索引为 ['min', 'mean', 'max']
的 DataFrame,那么你可以使用 groupby/apply
调用该函数(每组一次)并根据需要连接结果:
import numpy as np
import pandas as pd
def myfunc(g):
result = pd.DataFrame({'min':np.min(g),
'mean':np.mean(g),
'max':np.max(g)}).T
return result
df = pd.DataFrame({'A': [1, 1, 1, 1, 2, 2, 3],
'B': [10, 12, 11, 10, 11, 12, 14],
'C': [22, 20, 8, 10, 13, 10, 0],
'D': [14, 37, 18, 6, 4, 12, 5]})
result = df.groupby('A')[['B','C']].apply(myfunc)
result = result.unstack(level=-1)
print(result)
打印
B C
max mean min max mean min
A
1 12.0 10.75 10.0 22.0 15.0 8.0
2 12.0 11.50 11.0 13.0 11.5 10.0
3 14.0 14.00 14.0 0.0 0.0 0.0
对于可能 运行 跨越此问题且不需要自定义函数的其他人,请注意
您应该始终使用 builtin aggregators(在下面,由
字符串 'min'
、'mean'
和 'max'
) 如果可能的话。他们表现得比
自定义 Python 函数。令人高兴的是,在这个玩具问题中,它产生了预期的结果:
In [99]: df.groupby('A')[['B','C']].agg(['min','mean','max'])
Out[99]:
B C
min mean max min mean max
A
1 10 10.75 12 8 15.0 22
2 11 11.50 12 10 11.5 13
3 14 14.00 14 0 0.0 0
这样的事情可能会奏效。
df2.groupby('A')[['B','C']]
aggregated = df2.agg(['min', 'mean', 'max'])
那么您可以使用交换级别来交换列顺序
aggregated.columns = aggregated.columns.swaplevel(0, 1)
aggregated.sortlevel(0, axis=1, inplace=True)
我有一个看起来像这样的 DataFrame:
A B C D
1 10 22 14
1 12 20 37
1 11 8 18
1 10 10 6
2 11 13 4
2 12 10 12
3 14 0 5
和一个看起来像这样的函数(注意:它实际上在做一些更复杂的事情,不能轻易分成三个独立的调用,但为了清楚起见,我进行了简化):
def myfunc(g):
return min(g), mean(g), max(g)
我想在 A
上使用 groupby
和 myfunc
以获得列 B
和 C
上的输出(忽略 D
) 像这样:
B C
min mean max min mean max
A
1 10 10.75 12 8 15.0 22
2 11 11.50 12 10 11.5 13
3 14 14.00 14 0 0.0 0
我可以做到以下几点:
df2.groupby('A')[['B','C']].agg(
{
'min': lambda g: myfunc(g)[0],
'mean': lambda g: myfunc(g)[1],
'max': lambda g: myfunc(g)[2]
})
但是——除了这个丑陋和多次调用 myfunc
——我最终得到
max mean min
B C B C B C
A
1 12 22 10.75 15.0 10 8
2 12 13 11.50 11.5 11 10
3 14 0 14.00 0.0 14 0
我可以使用 .swaplevel(axis=1)
来交换列级别,但即使这样 B
和 C
仍然在多个重复的列中,并且通过多个函数调用感觉就像在咆哮错误的树。
如果你安排 myfunc
到 return 列为 ['A','B','C','D']
行索引为 ['min', 'mean', 'max']
的 DataFrame,那么你可以使用 groupby/apply
调用该函数(每组一次)并根据需要连接结果:
import numpy as np
import pandas as pd
def myfunc(g):
result = pd.DataFrame({'min':np.min(g),
'mean':np.mean(g),
'max':np.max(g)}).T
return result
df = pd.DataFrame({'A': [1, 1, 1, 1, 2, 2, 3],
'B': [10, 12, 11, 10, 11, 12, 14],
'C': [22, 20, 8, 10, 13, 10, 0],
'D': [14, 37, 18, 6, 4, 12, 5]})
result = df.groupby('A')[['B','C']].apply(myfunc)
result = result.unstack(level=-1)
print(result)
打印
B C
max mean min max mean min
A
1 12.0 10.75 10.0 22.0 15.0 8.0
2 12.0 11.50 11.0 13.0 11.5 10.0
3 14.0 14.00 14.0 0.0 0.0 0.0
对于可能 运行 跨越此问题且不需要自定义函数的其他人,请注意
您应该始终使用 builtin aggregators(在下面,由
字符串 'min'
、'mean'
和 'max'
) 如果可能的话。他们表现得比
自定义 Python 函数。令人高兴的是,在这个玩具问题中,它产生了预期的结果:
In [99]: df.groupby('A')[['B','C']].agg(['min','mean','max'])
Out[99]:
B C
min mean max min mean max
A
1 10 10.75 12 8 15.0 22
2 11 11.50 12 10 11.5 13
3 14 14.00 14 0 0.0 0
这样的事情可能会奏效。
df2.groupby('A')[['B','C']]
aggregated = df2.agg(['min', 'mean', 'max'])
那么您可以使用交换级别来交换列顺序
aggregated.columns = aggregated.columns.swaplevel(0, 1)
aggregated.sortlevel(0, axis=1, inplace=True)