问题可以归结为三个步骤:
1、如何找到每个月的第三个星期三?
这可能不是最优雅的解决方案,但您可以
通过掩蔽过滤掉每个月的第三个星期三
a熊猫
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)
将结果列表转换为
日期时间索引
因此,您可以将其用作步骤2中箱子的下限。
2.如何存储数据帧的值?
然后,一旦您将桶列表作为
日期时间索引
,您可以简单地
使用
panda's cut function
将每个日期分配给一个存储桶
. 将日期列转换为整数,然后将其传递到
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
3、如何聚合装箱数据帧?
现在就这么简单
使用
groupby
得到每个组合的总和
名称、项目和存储桶:
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 values are excluded from groupby
. 如果您还需要对这些数据进行求和,那么最简单的方法可能是确保您的存储桶列表在输入范围内的每个日期都至少有一个存储桶。
编辑:步骤2需要pandas版本>=0.18.1.