パンダのgroupbyとローリングウィンドウ
グループ化機能を適用した後、特定の期間の1つのフィールドの合計を計算しようとしています。
私のデータセットは次のようになります。
Date Company Country Sold
01.01.2020 A BE 1
02.01.2020 A BE 0
03.01.2020 A BE 1
03.01.2020 A BE 1
04.01.2020 A BE 1
05.01.2020 B DE 1
06.01.2020 B DE 0
行ごとに新しい列を追加して、過去7日間の販売済みの合計を計算します(各グループ「会社、国」ごと、現在の日は含まれません)。
Date Company Country Sold LastWeek_Count
01.01.2020 A BE 1 0
02.01.2020 A BE 0 1
03.01.2020 A BE 1 1
03.01.2020 A BE 1 1
04.01.2020 A BE 1 3
05.01.2020 B DE 1 0
06.01.2020 B DE 0 1
次のことを試しましたが、現在の日付も含まれており、同じ日付、つまり2020年1月3日に異なる値が表示されます。
df['LastWeek_Count'] = df.groupby(['Company', 'Country']).rolling(7, on ='Date')['Sold'].sum().reset_index()
これらの計算を実行するために使用できるパンダの組み込み関数はありますか?
回答
1つの方法は、最初に、一時DFを使用して、各グループ(['Date'、 'Company'、 'Country'])のSold値を1行に統合することです。
その後、あなたの適用.groupby
では、.rolling
8行の間隔で。
合計を計算した後、各行の値を[販売済み]列の値で減算し、その列を元のDFに追加します。.merge
#convert Date column to datetime
df['Date'] = pd.to_datetime(df['Date'], format='%d.%m.%Y')
#create a temporary DataFrame
df2 = df.groupby(['Date', 'Company', 'Country'])['Sold'].sum().reset_index()
#calc the lastweek
df2['LastWeek_Count'] = (df2.groupby(['Company', 'Country'])
.rolling(8, min_periods=1, on = 'Date')['Sold']
.sum().reset_index(drop=True)
)
#subtract the value of 'lastweek' from the current 'Sold'
df2['LastWeek_Count'] = df2['LastWeek_Count'] - df2['Sold']
#add th2 new column in the original DF
df.merge(df2.drop(columns=['Sold']), on = ['Date', 'Company', 'Country'])
#output:
Date Company Country Sold LastWeek_Count
0 2020-01-01 A BE 1 0.0
1 2020-01-02 A BE 0 1.0
2 2020-01-03 A BE 1 1.0
3 2020-01-03 A BE 1 1.0
4 2020-01-04 A BE 1 3.0
5 2020-01-05 B DE 1 0.0
6 2020-01-06 B DE 0 1.0
の.rolling
ウィンドウを使用して8
から、(グループ化された行ごとに)日付の合計を減算して、過去7日間を効果的に取得できます。このサンプルデータについても、渡す必要がありmin_periods=1
ます(そうでない場合はNaN
値を取得しますが、実際のデータセットについては、<であるウィンドウで何をするかを決定する必要があります8
)。
次に、の.rolling
ウィンドウから、関連する8
別.groupby
の列を実行しますが、Date
今回も含めてmax
、新しく作成されたLastWeek_Count
列の値を取得します。max
1日に複数のレコードがあるため、を取得する必要があります。したがって、最大を取得することにより、あたりの合計合計量を取得することになりますDate
。
その後、別にグループ化されとるシリーズ作成sum
あたりをDate
。最後のステップで、ローリング8日間の最大値から日付ごとの合計を減算します。これは、次のオフセットのパラメーターがないため、過去7日間の合計を取得する方法の回避策です.rolling
。
df['Date'] = pd.to_datetime(df['Date'], dayfirst=True)
df['LastWeek_Count'] = df.groupby(['Company', 'Country']).rolling(8, min_periods=1, on='Date')['Sold'].sum().reset_index()['Sold']
df['LastWeek_Count'] = df.groupby(['Company', 'Country', 'Date'])['LastWeek_Count'].transform('max')
s = df.groupby(['Company', 'Country', 'Date'])['Sold'].transform('sum')
df['LastWeek_Count'] = (df['LastWeek_Count']-s).astype(int)
Out[17]:
Date Company Country Sold LastWeek_Count
0 2020-01-01 A BE 1 0
1 2020-01-02 A BE 0 1
2 2020-01-03 A BE 1 1
3 2020-01-03 A BE 1 1
4 2020-01-04 A BE 1 3
5 2020-01-05 B DE 1 0
6 2020-01-06 B DE 0 1