使用分类方式创建组,并将索引复制到其他列



考虑下面的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

最新更新