[英]Python: Grouping values of different columns into time buckets
假設你有這個DataFrame:
Name Item Date value1 value2
Marc bike 21-Dec-17 7 1000
Marc bike 05-Jan-18 9 2000
Marc bike 27-Jul-18 4 500
John house 14-Dec-17 4 500
John house 02-Feb-18 6 500
John house 07-Feb-18 8 1000
John house 16-Feb-18 2 1000
John house 05-Dec-21 7 1000
John house 27-Aug-25 8 500
John car 17-Apr-18 4 500
我想將value1和value2分成每個名稱 - 項目組合的月度桶(每個第3個星期三,接下來的48個月)。
所以每個組合有49個時間段,每個月的值1和值2之和:Marc / bike,John / house,John / car,...
John / house的解決方案如下:
Name Item TimeBucket value1 value2
John house 20-Dec-17 4 500
John house 17-Jan-18 0 0
John house 21-Feb-18 16 2500
John house 21-Mar-18 0 0
John house 18-Apr-18 0 0
John house … 0 0
John house 17-Nov-21 0 0
John house 15-Dec-21 7 1000
John house rest 8 500
我不能用大熊貓得到一個結果。 我能想到的唯一解決方案是在數據幀中逐行迭代,但我真的想避免這樣做。 有一種優雅的方式嗎?
問題實際上歸結為三個步驟:
這可能不是最優雅的解決方案,但您可以通過屏蔽包含時間范圍內每天的大熊貓DatetimeIndex
來過濾掉每個月的第三個星期三 。
# generate a DatetimeIndex for all days in the relevant time frame
from datetime import datetime
start = datetime(2017, 12, 1)
end = datetime(2022, 1, 31)
days = pd.date_range(start, end, freq='D')
# filter out only the third wednesday of each month
import itertools
third_wednesdays = []
for year, month in itertools.product(range(2017, 2023), range(1,13)):
mask = (days.weekday == 2) & \
(days.year == year) & \
(days.month == month)
if len(days[mask]) > 0:
third_wednesdays.append(days[mask][2])
bucket_lower_bounds = pd.DatetimeIndex(third_wednesdays)
將結果列表轉換為DatetimeIndex
以便在步驟2中將其用作bin的下限。
然后,一旦您將桶列表作為DatetimeIndex
,您只需使用panda的cut函數將每個日期分配給存儲桶 。 在將日期列傳遞給cut
之前將其轉換為整數,然后將結果轉換回日期:
time_buckets = pd.to_datetime(
pd.cut(
x = pd.to_numeric(df['Date']),
bins = pd.to_numeric(bucket_lower_bounds),
labels = bucket_lower_bounds[:-1]
)
)
系列time_buckets
將原始數據框的每個索引值分配給存儲桶的下限。 我們現在可以簡單地將它添加到原始數據框中:
df['TimeBucket'] = time_buckets
結果應該看起來像這樣(不是說NaT
代表“休息”桶):
Name Item Date value1 value2 TimeBucket
0 Marc bike 2017-12-21 7 1000 2017-12-20
1 Marc bike 2018-01-05 9 2000 2017-12-20
2 Marc bike 2018-07-27 4 500 2018-07-18
3 John house 2017-12-14 4 500 NaT
4 John house 2018-02-02 6 500 2018-01-17
5 John house 2018-02-07 8 1000 2018-01-17
6 John house 2018-02-16 2 1000 2018-01-17
7 John house 2021-12-05 7 1000 2021-11-17
8 John house 2025-08-27 8 500 NaT
9 John car 2018-04-17 4 500 2018-03-21
現在就像使用groupby
獲取 name,item和bucket的每個組合的總和一樣簡單:
df.groupby(['Name','Item','TimeBucket']).sum()
結果:
Name Item TimeBucket value1 value2
John car 2018-03-21 4 500
house 2018-01-17 16 2500
2021-11-17 7 1000
Marc bike 2017-12-20 16 3000
2018-07-18 4 500
不幸的是, NaT值被排除在groupby之外 。 如果您還需要對這些進行求和,也許最簡單的方法是確保您的存儲桶列表在輸入范圍內的每個日期都至少有一個存儲桶。
編輯:步驟2需要pandas版本> = 0.18.1。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.