当前接受的答案的后半部分已经过时,并且有两个废弃功能。首先,您不能再将字典嵌套字典传递给
agg
groupby方法。其次,永远不要使用
.ix
。
如果您希望同时处理两个单独的列,我建议使用
apply
方法,该方法会隐式地将DataFrame传递给应用的函数。让我们使用与上面类似的数据框。
df = pd.DataFrame(np.random.rand(4,4), columns=list('abcd'))
df['group'] = [0, 0, 1, 1]
df
a b c d group
0 0.418500 0.030955 0.874869 0.145641 0
1 0.446069 0.901153 0.095052 0.487040 0
2 0.843026 0.936169 0.926090 0.041722 1
3 0.635846 0.439175 0.828787 0.714123 1
一个从列名映射到聚合函数的字典仍然是执行聚合的一种完全有效的方式。
df.groupby('group').agg({'a':['sum', 'max'],
'b':'mean',
'c':'sum',
'd': lambda x: x.max() - x.min()})
a b c d
sum max mean sum <lambda>
group
0 0.864569 0.446069 0.466054 0.969921 0.341399
1 1.478872 0.843026 0.687672 1.754877 0.672401
如果你不喜欢那个丑陋的lambda列名,你可以使用一个普通函数,并为特殊的__name__属性提供一个自定义名称,就像这样:
def max_min(x):
return x.max() - x.min()
max_min.__name__ = 'Max minus Min'
df.groupby('group').agg({'a':['sum', 'max'],
'b':'mean',
'c':'sum',
'd': max_min})
a b c d
sum max mean sum Max minus Min
group
0 0.864569 0.446069 0.466054 0.969921 0.341399
1 1.478872 0.843026 0.687672 1.754877 0.672401
使用apply
并返回一个Series
现在,如果你有多个需要相互作用的列,那么你不能使用agg
,因为它会隐式地将一个Series传递给聚合函数。当使用apply
时,整个分组作为DataFrame被传递到函数中。
我建议创建一个单独的自定义函数,返回所有聚合的Series。使用Series的索引作为新列的标签:
def f(x):
d = {}
d['a_sum'] = x['a'].sum()
d['a_max'] = x['a'].max()
d['b_mean'] = x['b'].mean()
d['c_d_prodsum'] = (x['c'] * x['d']).sum()
return pd.Series(d, index=['a_sum', 'a_max', 'b_mean', 'c_d_prodsum'])
df.groupby('group').apply(f)
a_sum a_max b_mean c_d_prodsum
group
0 0.864569 0.446069 0.466054 0.173711
1 1.478872 0.843026 0.687672 0.630494
如果你喜欢使用多级索引,你仍然可以返回一个像这样的Series:
def f_mi(x):
d = []
d.append(x['a'].sum())
d.append(x['a'].max())
d.append(x['b'].mean())
d.append((x['c'] * x['d']).sum())
return pd.Series(d, index=[['a', 'a', 'b', 'c_d'],
['sum', 'max', 'mean', 'prodsum']])
df.groupby('group').apply(f_mi)
a b c_d
sum max mean prodsum
group
0 0.864569 0.446069 0.466054 0.173711
1 1.478872 0.843026 0.687672 0.630494