累積合計によるパンダグループ


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.groupbydf.agg(lambda x: cumsum(x))無駄にします。


平日で集計する必要があると本当に確信していますか?それはインデックスを失い、また、複数の週がある場合、累積合計はあまり意味がありません。dmitry-andreevと@vjaykyによる回答は、代わりに各名前の日数のシーケンスにわたってcumsumを計算します。日付列もある場合にこれをどのように拡張できるかを考えてください。グループ化して集計する前に、エントリを並べ替えることができます。
エリアスハッスル2018年

回答:


89

これでうまくいくはずです。2groupby()回必要です。

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年

5
1)、2番目の数値40のように、累積は複数の行からのものであるため、インデックス番号は10 + 20 + 10であるため、どのインデックス値を取得する必要がありますか?1、2または3?それでは、namedayを使い続けましょうmultiIndex。これは、より理にかなっています(必要に応じてインデックスreset_index()を取得するためint)。2)、level=[0]手段groupbyは、の第1レベルMultiIndex、すなわち列によって動作することですname
CT Zhu

CTに感謝します。私は後でそれを理解し、問題を解決するためにreset_index()を試しました。詳細な説明ありがとうございます!
user3694373 2014年

4
微妙なバグがあります。最初のgroupby()デフォルトではキーの並べ替えが行われるため、入力データセットの下部にJack-Thursday行を追加すると、予期しない結果が発生します。そして、groupby()レベル名で作業できるので、私はdf.groupby(['name', 'day'], sort=False).sum().groupby(by='name').cumsum().reset_index()あまりわかりにくいと思います。
ニコライ2018年

列の名前をどのように変更しますか?
ジョナサンラム

47

これはパンダ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 2016年

2
この答えは(と同等と思われることを注意@vjaykyによって簡単な解決策は)によって集約しませんnamedayで累積和を計算する前にname(注:結果でジャック+火曜日のための2行があります)。これが、CTZhuによる回答よりも簡単な理由です。
ニコライ2018年

39

@Dmitryの回答の変更。これはより単純で、パンダ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段階の集計が必要ない場合、これは最も簡単な解決策のようです。
ニコライ2018年

私が特に好きではない唯一の部分は、それが私のintdtypeをfloatに変換したことです。
クリスファー

これは、グループ部分のcumsumに対して受け入れられた回答である必要があります。@ChrisFarrパンダ1.0.3の時点では、フロートに変換されなくなったようです。
ルイ・ヤン

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を呼び出す必要がないことを意味します

これを投稿してくれてありがとう、それは私がここで何が起こっているのかを理解するのに役立ちました!両方の列をMultiIndexに移動するだけgroupby().sum()でなく、Jack + Tuesdayの2つの値も合計することに注意してください。また、インデックスはの前にすでに設定されているため、この場合は効果がないようです。また、データフレームの列から名前/日を削除するため、結果の数値列を元のデータフレームに追加するか(vjaykyやDmitryが提案したように)、名前/日をインデックスに移動し、後でreset_indexを実行する必要があります。as_index=Falsegroupbygroupby().cumsum()
ニコライ2018年

7

あなたが使用する必要があります

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の値)。
ニコライ2018年

@Nickolayはちょうど別の答えを追加しましたそれが機能するかどうか私に知らせてください
18年

私の例のようにグローバルな現在の合計を計算するかどうかは
わかり

pandas.series.cumsum()の代わりにラムダx:x.cumsum()を使用するのはなぜですか?
金華王

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.