팬더 그룹 별 누적 합계


93

Pandas 데이터 프레임에 누적 합계 열을 추가하여 다음을 수행하고 싶습니다.

name | day       | no
-----|-----------|----
Jack | Monday    | 10
Jack | Tuesday   | 20
Jack | Tuesday   | 10
Jack | Wednesday | 50
Jill | Monday    | 40
Jill | Wednesday | 110

된다 :

Jack | Monday     | 10  | 10
Jack | Tuesday    | 30  | 40
Jack | Wednesday  | 50  | 90
Jill | Monday     | 40  | 40
Jill | Wednesday  | 110 | 150

나는 다양한 콤보 시도 df.groupby하고 df.agg(lambda x: cumsum(x))아무 소용합니다.


주중에 집계를 원하십니까? 그것은 지수를 잃고, 또한 여러 주가있는 경우 누적 합계는 의미가 없습니다. dmitry-andreev 및 @vjayky의 답변은 대신 각 이름의 날짜 시퀀스에 대한 cumsum을 계산합니다. 날짜 열도있는 경우 항목을 그룹화 및 집계하기 전에 정렬 할 수있는 경우 이것이 어떻게 확장 될 수 있는지 생각해보십시오.
Elias Hasle 2018

답변:


89

이 작업을 수행해야하며 groupby()두 번 필요합니다 .

df.groupby(['name', 'day']).sum() \
  .groupby(level=0).cumsum().reset_index()

설명:

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

# sum per name/day
print( df.groupby(['name', 'day']).sum() )
                 no
name day           
Jack Monday      10
     Tuesday     30
     Wednesday   50
Jill Monday      40
      Wednesday  110

# cumulative sum per name/day
print( df.groupby(['name', 'day']).sum() \
         .groupby(level=0).cumsum() )
                 no
name day           
Jack Monday      10
     Tuesday     40
     Wednesday   90
Jill Monday      40
     Wednesday  150

첫 번째 합계의 결과 인 데이터 프레임은 'name'및에 의해 인덱싱 됩니다 'day'. 인쇄하여 볼 수 있습니다

df.groupby(['name', 'day']).sum().index 

누적 합계를 계산할 때 'name'첫 번째 인덱스 (수준 0)에 해당하는으로 계산할 수 있습니다 .

마지막으로을 사용 reset_index하여 이름을 반복하십시오.

df.groupby(['name', 'day']).sum().groupby(level=0).cumsum().reset_index()

   name        day   no
0  Jack     Monday   10
1  Jack    Tuesday   40
2  Jack  Wednesday   90
3  Jill     Monday   40
4  Jill  Wednesday  150

3
답변 해주셔서 감사합니다. 그래도 몇 가지 질문이있었습니다. 1. 'level = [0]'이 무엇을 의미하는지 설명해 주시겠습니까? 2. 또한 보시다시피 이전에 데이터 프레임에 행 번호가 있었고 누적 합계를 수행하면이 행 번호가 사라집니다. 그들을 되 찾을 방법이 있습니까?
user3694373 2014-10-16

5
1), 두 번째 숫자 40과 같이 누적이 여러 행에서 나왔으므로 인덱스 번호는 가야합니다. 10 + 20 + 10, 어떤 인덱스 값을 가져와야합니까? 1, 2 또는 3? 따라서 더 나은 의미가있는 namedayas를 계속 사용하겠습니다 multiIndex( 원하는 경우 색인 reset_index()을 얻기 위해 int). 2) level=[0]수단 groupbyMultiIndex, 즉 column 의 첫 번째 수준에서 작동하는 것 name입니다.
CT Zhu

감사합니다 CT. 나는 나중에 그것을 이해하고 내 문제를 해결하기 위해 reset_index ()를 시도했습니다. 자세한 설명 감사합니다!
user3694373

4
미묘한 버그가 있습니다. 첫 번째는 groupby()기본적으로 키 정렬이므로 입력 데이터 세트의 맨 아래에 Jack-Thursday 행을 추가하면 예기치 않은 결과가 발생합니다. 그리고 groupby()레벨 이름으로 작업 할 수 있기 때문에 df.groupby(['name', 'day'], sort=False).sum().groupby(by='name').cumsum().reset_index()덜 애매합니다.
Nickolay

열 이름을 어떻게 바꾸나요?
Jonathan Lam

47

이것은 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

df에 다시 추가하는 방법을 보여주는 것은 정말 도움이됩니다. 변환을 사용해 보았지만 cumsum ()에서는 잘 작동하지 않았습니다.
zerovector

2
이 대답합니다 (동등 보인다 주 @vjayky에 의한 간단한 해결책은 )에 의해 집계하지 않습니다 nameday의해 누적 합계를 계산하기 전에 name(참고 : 결과에 잭 + 화요일 2 개 행이). 이것이 CT Zhu의 답변 보다 간단하게 만드는 것 입니다.
Nickolay

39

@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

2
질문에서 요청한대로 2 단계 집계가 필요하지 않은 경우 가장 간단한 솔루션 인 것 같습니다 .
Nickolay

내가 특별히 좋아하지 않는 유일한 부분은 int dtype을 float로 변환했다는 것입니다.
Chris Farr

이것은 그룹 부분의 cumsum에 대해 허용되는 대답이어야합니다. @ChrisFarr pandas 1.0.3부터는 더 이상 float로 변환되지 않는 것 같습니다.
Louis Yang

8

당신은 사용해야합니다

df['cum_no'] = df.no.cumsum()

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

여기에 이미지 설명 입력


3
이렇게하면 각 그룹에 대한 별도의 합계 대신 글로벌 누적 합계가 계산됩니다. 따라서 Jill-Monday에는 130의 값이 할당됩니다 ( 90, 모든 Jack 값의 합계로 + 40, Jill-Monday 값).
Nickolay

@Nickolay는 방금 작동하는지 알려주는 또 다른 답변을 추가했습니다
sushmit

내 예제 행 3에 따라 글로벌 누계를 계산하는지 확실하지 않습니다.
sushmit

pandas.series.cumsum () 대신 람다 x : x.cumsum ()을 사용하는 이유는 무엇입니까?
Jinhua Wang

7

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를 호출 할 필요가 없음을 의미합니다.

게시 해 주셔서 감사합니다. 여기에서 무슨 일이 일어나고 있는지 이해하는 데 도움이되었습니다. 참고 groupby().sum()되지 않은 단지 MultiIndex에 모두 열 이동은 - 그것은 또한 잭 + 화요일 두 값을 요약한다. 그리고 as_index=False인덱스가 이미 전에 설정 되었으므로이 경우에는 아무런 영향을 미치지 않는 것 같습니다 groupby. 그리고 groupby().cumsum()데이터 프레임의 열에서 이름 / 일을 nukes하기 때문에 결과 숫자 열을 원래 데이터 프레임에 추가하거나 (예 : vjayky 및 Dmitry가 제안 함) 색인으로 이름 / 일을 이동 한 다음 나중에 reset_index해야합니다.
Nickolay

0

data.csv :

name,day,no
Jack,Monday,10
Jack,Tuesday,20
Jack,Tuesday,10
Jack,Wednesday,50
Jill,Monday,40
Jill,Wednesday,110

암호:

import numpy as np
import pandas as pd

df = pd.read_csv('data.csv')
print(df)
df = df.groupby(['name', 'day'])['no'].sum().reset_index()
print(df)
df['cumsum'] = df.groupby(['name'])['no'].apply(lambda x: x.cumsum())
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
   name        day   no
0  Jack     Monday   10
1  Jack    Tuesday   30
2  Jack  Wednesday   50
3  Jill     Monday   40
4  Jill  Wednesday  110
   name        day   no  cumsum
0  Jack     Monday   10      10
1  Jack    Tuesday   30      40
2  Jack  Wednesday   50      90
3  Jill     Monday   40      40
4  Jill  Wednesday  110     150
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.