熊猫群累计总和

kc2*_*819 65 python pandas

我想在我的Pandas数据帧中添加累积和列,以便:

name | day       | no
-----|-----------|----
Jack | Monday    | 10
Jack | Tuesday   | 20
Jack | Tuesday   | 10
Jack | Wednesday | 50
Jill | Monday    | 40
Jill | Wednesday | 110
Run Code Online (Sandbox Code Playgroud)

变为:

Jack | Monday     | 10  | 10
Jack | Tuesday    | 30  | 40
Jack | Wednesday  | 50  | 90
Jill | Monday     | 40  | 40
Jill | Wednesday  | 110 | 150
Run Code Online (Sandbox Code Playgroud)

我试过各种连击df.groupbydf.agg(lambda x: cumsum(x))无济于事.提前致谢!

CT *_*Zhu 59

这应该做,需要groupby()两次.

In [52]:

print df
   name        day   no
0  Jack     Monday   10
1  Jack    Tuesday   20
2  Jack    Tuesday   10
3  Jack  Wednesday   50
4  Jill     Monday   40
5  Jill  Wednesday  110
In [53]:

print df.groupby(by=['name','day']).sum().groupby(level=[0]).cumsum()
                 no
name day           
Jack Monday      10
     Tuesday     40
     Wednesday   90
Jill Monday      40
     Wednesday  150
Run Code Online (Sandbox Code Playgroud)

注意,结果DataFrameMultiIndex.

  • 谢谢你的回答.我确实有一些疑问:1.你能解释一下'level = [0]'是什么意思吗?2.此外,正如您所看到的,您之前的数据框中有行号,一旦您执行累积总和,这些行号就会消失.有没有办法让他们回来? (3认同)
  • 1),索引号必须去,因为cumsum来自多行,如第二个数字40,是10 + 20 + 10,它应该得到哪个索引值?1,2或3?所以,让我们继续使用`name`和`day`作为`multiIndex`,这更有意义(`reset_index()`得到'int`索引,如果需要的话).2),`level = [0]`表示'groupby`是由`MultiIndex`的第1级操作,即列`name`. (3认同)
  • 有一个微妙的错误:第一个`groupby()`默认对键进行排序,所以如果你在输入数据集的底部添加一个Jack-Thursday行,你将得到意想不到的结果.由于`groupby()`可以使用级别名称,我找到`df.groupby(['name','day'],sort = False).sum().groupby(by ='name').cumsum() .reset_index()`不那么神秘. (3认同)
  • 这是一个多么残酷的方法来达到这个结果,希望这在熊猫中很简单 (2认同)

Dmi*_*eev 38

这适用于pandas 0.16.2

In[23]: print df
        name          day   no
0      Jack       Monday    10
1      Jack      Tuesday    20
2      Jack      Tuesday    10
3      Jack    Wednesday    50
4      Jill       Monday    40
5      Jill    Wednesday   110
In[24]: df['no_cumulative'] = df.groupby(['name'])['no'].apply(lambda x: x.cumsum())
In[25]: print df
        name          day   no  no_cumulative
0      Jack       Monday    10             10
1      Jack      Tuesday    20             30
2      Jack      Tuesday    10             40
3      Jack    Wednesday    50             90
4      Jill       Monday    40             40
5      Jill    Wednesday   110            150
Run Code Online (Sandbox Code Playgroud)

  • 请注意,此答案(似乎等同于 [@vjayky 的更简单的解决方案](/sf/answers/3470475361/))在通过 `name` 和 `day` 计算累积总和之前不会聚合name`(注意:结果中有 2 行 Jack+Tuesday)。这就是使它比 [CT Zhu 的答案](/sf/answers/1585583191/) 更简单的原因。 (3认同)

小智 22

修改@Dmitry的答案.这更简单,适用于pandas 0.19.0:

print(df) 

 name        day   no
0  Jack     Monday   10
1  Jack    Tuesday   20
2  Jack    Tuesday   10
3  Jack  Wednesday   50
4  Jill     Monday   40
5  Jill  Wednesday  110

df['no_csum'] = df.groupby(['name'])['no'].cumsum()

print(df)
   name        day   no  no_csum
0  Jack     Monday   10       10
1  Jack    Tuesday   20       30
2  Jack    Tuesday   10       40
3  Jack  Wednesday   50       90
4  Jill     Monday   40       40
5  Jill  Wednesday  110      150
Run Code Online (Sandbox Code Playgroud)

  • 如果您 [不需要两步聚合](/sf/ask/1585558341/#comment88124762_34130874),这似乎是最简单的解决方案,如问题中所要求. (2认同)

sus*_*mit 9

你应该使用

df['cum_no'] = df.no.cumsum()
Run Code Online (Sandbox Code Playgroud)

http://pandas.pydata.org/pandas-docs/version/0.19.2/generated/pandas.DataFrame.cumsum.html

另一种方式

import pandas as pd
df = pd.DataFrame({'C1' : ['a','a','a','b','b'],
           'C2' : [1,2,3,4,5]})
df['cumsum'] = df.groupby(by=['C1'])['C2'].transform(lambda x: x.cumsum())
df
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

  • 这将计算全局运行总计,而不是为每个组分别计算单独的总和。因此,给Jill-Monday分配了一个值130(“ 90”,作为所有Jack值的总和,加上“`40”,即Jill-Monday的值)。 (2认同)

小智 5

而不是df.groupby(by=['name','day']).sum().groupby(level=[0]).cumsum() (见上文)你也可以做df.set_index(['name', 'day']).groupby(level=0, as_index=False).cumsum()

  • df.groupby(by=['name','day']).sum() 实际上只是将两列都移动到MultiIndex
  • as_index=False 意味着您之后不需要调用reset_index