1. ホーム
  2. python

Python - GroupByオブジェクトのためのローリング関数

2023-11-01 03:28:15

質問

時系列オブジェクト grouped という型の <pandas.core.groupby.SeriesGroupBy object at 0x03F1A9F0> . grouped.sum() は望ましい結果をもたらしますが、rolling_sum が groupby オブジェクトに適用することができません。にローリング関数を適用する方法はあるのでしょうか? groupby オブジェクトに適用する方法はありますか?例えば

x = range(0, 6)
id = ['a', 'a', 'a', 'b', 'b', 'b']
df = DataFrame(zip(id, x), columns = ['id', 'x'])
df.groupby('id').sum()
id    x
a    3
b   12

しかし、こんなのが欲しい。

  id  x
0  a  0
1  a  1
2  a  3
3  b  3
4  b  7
5  b  12

どのように解決するのですか?

累積和

質問に直接答えるために、cumsumメソッドは目的の系列を生成するでしょう。

In [17]: df
Out[17]:
  id  x
0  a  0
1  a  1
2  a  2
3  b  3
4  b  4
5  b  5

In [18]: df.groupby('id').x.cumsum()
Out[18]:
0     0
1     1
2     3
3     3
4     7
5    12
Name: x, dtype: int64

グループごとのpandasローリング関数

より一般的には、以下のように任意のローリング関数を各グループに適用することができます(@kekert がコメントした新しい .rolling メソッドを使用します)。戻り値の型は、以前の(非推奨の)pd.rolling_*メソッドとは異なる、複数のインデックスを持つ系列であることに注意してください。

In [10]: df.groupby('id')['x'].rolling(2, min_periods=1).sum()
Out[10]:
id
a   0   0.00
    1   1.00
    2   3.00
b   3   3.00
    4   7.00
    5   9.00
Name: x, dtype: float64

グループごとのローリング関数を適用し、結果を元のデータフレームの順序で受け取るには、代わりにtransformを使用する必要があります。

In [16]: df.groupby('id')['x'].transform(lambda s: s.rolling(2, min_periods=1).sum())
Out[16]:
0    0
1    1
2    3
3    3
4    7
5    9
Name: x, dtype: int64


非推奨の方法

参考までに、今は非推奨のpandas.rolling_meanの挙動は以下の通りです。

In [16]: df.groupby('id')['x'].apply(pd.rolling_mean, 2, min_periods=1)
Out[16]: 
0    0.0
1    0.5
2    1.5
3    3.0
4    3.5
5    4.5