タイプ_<pandas.core.groupby.SeriesGroupBy object at 0x03F1A9F0>
_の時系列オブジェクトgrouped
があります。 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
_
注: @kekertで識別されるように、次のpandasパターンは廃止されました。以下の回答の現在のソリューションを参照してください。
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
In [17]: df.groupby('id')['x'].cumsum()
Out[17]:
0 0
1 1
2 3
3 3
4 7
5 12
この古い質問に出くわしたGoogle社員向け:
新しいガレットの回答に対する@kekertのコメントについて
df.groupby('id')['x'].rolling(2).mean()
廃止されたものではなく
df.groupby('id')['x'].apply(pd.rolling_mean, 2, min_periods=1)
奇妙なことに、新しい.rolling()。mean()アプローチは、最初にgroup_by列、次にインデックスでインデックス付けされたマルチインデックスシリーズを返すようです。一方、古いアプローチでは、元のdfインデックスで特異的にインデックス付けされたシリーズを返すだけで、おそらくあまり意味がありませんが、そのシリーズを元のデータフレームに新しい列として追加するのに非常に便利です。
だから、新しいrolling()メソッドを使用しても同じように動作する解決策を見つけたと思います:
df.groupby('id')['x'].rolling(2).mean().reset_index(0,drop=True)
あなたにシリーズを与える必要があります
0 0.0
1 0.5
2 1.5
3 3.0
4 3.5
5 4.5
列として追加できます:
df['x'] = df.groupby('id')['x'].rolling(2).mean().reset_index(0,drop=True)
これは、パンダの expanding メソッドをうまく一般化する別の方法です。
これは非常に効率的で、時系列などの固定ウィンドウで ローリングウィンドウの計算 に対しても完全に機能します。
# Import pandas library
import pandas as pd
# Prepare columns
x = range(0, 6)
id = ['a', 'a', 'a', 'b', 'b', 'b']
# Create dataframe from columns above
df = pd.DataFrame({'id':id, 'x':x})
# Calculate rolling sum with infinite window size (i.e. all rows in group) using "expanding"
df['rolling_sum'] = df.groupby('id')['x'].transform(lambda x: x.expanding().sum())
# Output as desired by original poster
print(df)
id x rolling_sum
0 a 0 0
1 a 1 1
2 a 2 3
3 b 3 3
4 b 4 7
5 b 5 12
メカニズムはわかりませんが、これは機能します。返される値はndarrayにすぎないことに注意してください。この方法で累積または「ローリング」関数を適用でき、同じ結果になるはずです。
cumprod
、cummax
、およびcummin
でテストしましたが、それらはすべてndarrayを返しました。 pandasは、これらの関数がシリーズを返すことを知っているので、関数は集約ではなく変換として適用されます。
In [35]: df.groupby('id')['x'].cumsum()
Out[35]:
0 0
1 1
2 3
3 3
4 7
5 12
編集:私はこの構文がシリーズを返すことに興味がありました:
In [54]: df.groupby('id')['x'].transform('cumsum')
Out[54]:
0 0
1 1
2 3
3 3
4 7
5 12
Name: x