考虑下面的MWE,最后有三行可选:
df = pd.DataFrame({'a': np.arange(100)*3})
(df.assign(mybins = lambda df: pd.cut(df['a'],bins=np.linspace(0,300,6)))
.groupby('mybins')
.sum()
#.apply(lambda x: x.sum())
#.apply(lambda x: x.count()/float(len(df))*100)
)
我有一个带有浮点数的DataFrame。我想把a列的箱子分组然后做一些计算。当我使用.sum
函数时,它按预期工作,它返回bin作为索引,并返回每个bin的和作为列值。
现在,当我使用apply函数来计算总和时,不知何故,groupby索引也被转换为数据框中的附加列'mybins',并且总和应用于两列。现在我有一列a是a
的和还有一列mybins是bin边的列表乘以sum(a)
。这不是我想要/期望的。
我的最终目标是使用apply
来计算百分比,但随后我得到一个错误(不支持的操作数类型),所以我需要修复这个奇怪的行为。我错过了什么?
这就是你想要的-注意.groupby('mybins')['a']
(['a']):
In [270]: %paste
(df.assign(mybins = lambda df: pd.cut(df['a'],bins=np.linspace(0,300,6)))
.groupby('mybins')['a']
#.sum()
#.apply(lambda x: x.sum())
.apply(lambda x: x.sum()/float(len(x))*100)
)
## -- End pasted text --
Out[270]:
mybins
(0, 60] 3150.0
(60, 120] 9150.0
(120, 180] 15150.0
(180, 240] 21150.0
(240, 300] 27000.0
Name: a, dtype: float64
顺便说一句,你可以用一种更习惯的方式达到同样的结果:
In [273]: %paste
(df.assign(mybins = lambda df: pd.cut(df['a'],bins=np.linspace(0,300,6)))
.groupby('mybins')
.mean() * 100
)
## -- End pasted text --
Out[273]:
a
mybins
(0, 60] 3150.0
(60, 120] 9150.0
(120, 180] 15150.0
(180, 240] 21150.0
(240, 300] 27000.0
解释:
给定:
In [33]: df
Out[33]:
s n s2 n2 n3
0 a 0.629772 a 6.297724 1
1 d 0.496197 d 4.961974 0
2 a 0.801868 a 8.018679 0
3 d 0.461914 d 4.619140 3
4 c 0.259175 c 2.591751 0
5 b 0.797740 b 7.977401 0
6 a 0.508496 a 5.084962 1
7 b 0.242306 b 2.423056 2
8 c 0.218082 c 2.180820 2
9 d 0.060125 d 0.601247 3
如果我们尝试使用.apply()
来总结组,我们得到:
In [34]: df.groupby('s').apply(lambda x: x.sum())
Out[34]:
s n s2 n2 n3
s
a aaa 1.940136 aaa 19.401364 2
b bb 1.040046 bb 10.400456 2
c cc 0.477257 cc 4.772571 2
d ddd 1.018236 ddd 10.182361 6
,因为apply()
将应用于所有列,包括groupby
列—本例中的s
用.apply(lambda x: print(x))
代替.apply(lambda x: x.sum())
证明
In [35]: df.groupby('s').apply(lambda x: print(x))
s n s2 n2 n3
0 a 0.629772 a 6.297724 1
2 a 0.801868 a 8.018679 0
6 a 0.508496 a 5.084962 1
s n s2 n2 n3
0 a 0.629772 a 6.297724 1
2 a 0.801868 a 8.018679 0
6 a 0.508496 a 5.084962 1
s n s2 n2 n3
5 b 0.797740 b 7.977401 0
7 b 0.242306 b 2.423056 2
s n s2 n2 n3
4 c 0.259175 c 2.591751 0
8 c 0.218082 c 2.180820 2
s n s2 n2 n3
1 d 0.496197 d 4.961974 0
3 d 0.461914 d 4.619140 3
9 d 0.060125 d 0.601247 3
Out[35]:
Empty DataFrame
Columns: []
Index: []
注1:您可以看到所有列,包括groupby
列
注2:你看到5组,而不是预期的4组。使用groupby,应用的函数会被额外调用一次,以查看是否可以进行某些优化。
现在让我们尝试使用.sum()
函数:
In [37]: df.groupby('s').sum()
Out[37]:
n n2 n3
s
a 1.940136 19.401364 2
b 1.040046 10.400456 2
c 0.477257 4.772571 2
d 1.018236 10.182361 6
sum()
足够聪明,可以删除所有非数字列,当应用sum
时,它也会删除groupby
列:
In [38]: df.groupby('n3').sum()
Out[38]:
n n2
n3
0 2.354980 23.549805
1 1.138269 11.382686
2 0.460388 4.603876
3 0.522039 5.220387
我们只是按另一个数字列n3
分组,sum()
没有应用于groupby
列