将函数应用于DataFrame GroupBy并返回较少的列

时间:2015-07-13 12:26:31

标签: python pandas

我想对DataFrame进行分组,然后应用多个列的函数返回单个结果。

In [25]: length = 100
In [26]: rnd = np.random.random
In [27]: df = pd.DataFrame(dict(group=np.random.choice(['a','b','c'], length), foo=rnd(length), bar=rnd(length)))
In [28]: df.head()
Out[28]: 
        bar       foo group
0  0.068853  0.201808     a
1  0.148494  0.722194     c
2  0.902275  0.865231     b
3  0.933513  0.843651     a
4  0.910224  0.671588     a

但是,如果我执行了aggregate,我会将结果返回两次(GroupBy后每个剩余列一次。)我做错了什么?

In [29]:  df.groupby('group').agg(lambda g: sum(g.bar + g.foo))
Out[29]: 
             bar        foo
group                      
a      36.937812  36.937812
b      33.021105  33.021105
c      30.274639  30.274639

我真正想要的只是Series,结果与Out[29]相同。

2 个答案:

答案 0 :(得分:3)

我认为这是因为agg倾向于保持与原始群组相同的ndim,而不是将群组从ndim=2挤压到ndim=1。这就是说,你的子组是nx2 ndarray,计算确实返回一个标量,然后它以1x2广播到非压缩ndarray(所以它仍然是2 d数组与原始列)。或者,换句话说,规则agg是在axis=0之间聚合子组数据帧(nx2),因此返回的形状必须为1x2。因此,即使您获得了标量结果,当.agg返回结果时,它也会被广播为1x2。

可以使用apply而不是agg修复此问题,因为apply对返回的形状没有约束。

df.groupby('group').apply(lambda g: sum(g.bar + g.foo))

group
a    39.4419
b    27.2982
c    25.3910
dtype: float64

答案 1 :(得分:1)

如果你不介意按步骤做,为什么不这样做:

In [52]:
df = df.groupby('group').sum()
df['foobar']=df.foo + df.bar
new_series = df.loc[:,'foobar']
new_series

Out[52]:
group
a        33.047944
b        30.503071
c        30.899891
Name: foobar, dtype: float64

In [53]:
type(new_series)

Out[53]:
pandas.core.series.Series