pandasの時系列データ処理で累積和を一定期間毎に算出する方法

pandasで時系列データなどの分析を行なう際、日毎や分毎などで累積和を算出したいケースがあると思います。

例えば、以下のような1ヵ月分のティックデータを1Tでresamplingしたohlcvに変換したいとします。
<img width="344" alt="スクリーンショット 2018-11-30 2.35.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/100746/6b60d5c9-7ef6-8f2b-c27c-ee9d684b34eb.png">

そこで、以下のような処理でcode毎のohlcvを作成します。

```
def gen_ohlcv_df(code):
    df_ohlcv_code = df[df['code'] == code]
    df_ohlcv_code = df_ohlcv_code.set_index('date')
    df_ohlcv_code = pd.concat([df_ohlcv_code['Price'].resample('T').ohlc(),
                               df_ohlcv_code['Trading volume'].resample('T').sum()], axis=1)
    return df_ohlcv_code
```

当然当該時刻にデータがない場合は欠損値になります。

<img width="460" alt="スクリーンショット 2018-11-30 2.52.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/100746/505d242b-85b5-0af1-3194-20f5b833c404.png">

ここで欠損値は直前の値で補間したいと思います。

```
def gen_ohlcv_df(code):
    df_ohlcv_code = df[df['code'] == code]
    df_ohlcv_code = df_ohlcv_code.set_index('date')
    df_ohlcv_code = pd.concat([df_ohlcv_code['Price'].resample('T').ohlc(),
                               df_ohlcv_code['Trading volume'].resample('T').sum()], axis=1)
    df_ohlcv_code = df_ohlcv_code.reset_index()
    
    # 欠損値を直前のデータで補間する
    df_ohlcv_code = df_ohlcv_code.interpolate(method='zero')
    
    return df_ohlcv_code
```

ohlcは良い感じになりました。
ここで、volumeは日毎の累積和で表示したいとします。

<img width="475" alt="スクリーンショット 2018-11-30 2.59.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/100746/0927d7c0-455a-42d7-c72e-36a0eae6a83a.png">

ところが、単純にcumsum()を当てると以下のように、volumeが全期間の累積和となってしまいます。

```
def gen_ohlcv_df(code):
    df_ohlcv_code = df[df['code'] == code]
    df_ohlcv_code = df_ohlcv_code.set_index('date')
    df_ohlcv_code = pd.concat([df_ohlcv_code['Price'].resample('T').ohlc(),
                               df_ohlcv_code['Trading volume'].resample('T').sum()], axis=1)
    df_ohlcv_code = df_ohlcv_code.reset_index()
    
    # Trading volumeの累積和をとる
    df_ohlcv_code['Trading volume'] = df_ohlcv_code['Trading volume'].cumsum()
    
    # 欠損値を直前のデータで補間する
    df_ohlcv_code = df_ohlcv_code.interpolate(method='zero')
    
    return df_ohlcv_code
```

<img width="454" alt="スクリーンショット 2018-11-30 3.05.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/100746/2c846dae-2dd7-1382-0c8d-9dce4123f639.png">
<img width="402" alt="スクリーンショット 2018-11-30 3.05.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/100746/93541011-093b-4557-3fc7-2f674578196e.png">


volumeは日毎にリセットして累積和を算出したいので、datetimeから暫定的に日付データのみのカラムを作成してgroupbyしてやることで解決します。

```
def gen_ohlcv_df(code):
    df_ohlcv_code = df[df['code'] == code]
    df_ohlcv_code = df_ohlcv_code.set_index('date')
    df_ohlcv_code = pd.concat([df_ohlcv_code['Price'].resample('T').ohlc(),
                               df_ohlcv_code['Trading volume'].resample('T').sum()], axis=1)
    df_ohlcv_code = df_ohlcv_code.reset_index()
    
    # groupbyのためのdayカラムを一時的に追加
    df_ohlcv_code['day'] = df_ohlcv_code['date'].map(lambda x: x.day)
    
    # 日単位でTrading volumeの累積和をとる
    df_ohlcv_code['Trading volume'] = df_ohlcv_code.groupby(['day'])['Trading volume'].cumsum()
    
    # dayカラムを削除
    df_ohlcv_code = df_ohlcv_code.drop('day', axis=1)
    
    # 欠損値を直前のデータで補間する
    df_ohlcv_code = df_ohlcv_code.interpolate(method='zero')
    
    return df_ohlcv_code
```

累積和を日毎に算出することができました。
<img width="400" alt="スクリーンショット 2018-11-30 3.14.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/100746/538fd3a0-f770-c857-f6d0-f8a944ddc637.png">

groupbyするデータを分や秒、週にする場合などは `x.day` の部分を `x.minute` などに適宜変更することで対応できます。