这个问题以前就有人问过,但我想进一步讨论。因为我没有足够的经验值,所以我无法评论这个问题,所以我重新发布了下面的链接,后面跟着我的评论:
使用pandas按日期范围分组
我相信这个问题的提问者想要在指定的时间间隔内(问题中指定了3天)将项目分组在一起。然而答案,包括正确的标记,与分组项目使用Grouper
频率的3天。这最终适合提问者,因为他最多只想将两个项目组合在一起,但如果扩展到三个、四个、五个或更多项目,会发生什么呢?
继续提问的示例代码(它与我自己的问题非常密切相关):
user_id date val
1 1-1-17 1
2 1-1-17 1
3 1-1-17 1
1 1-1-17 1
1 1-2-17 1
2 1-2-17 1
2 1-10-17 1
3 2-1-17 1
3 2-2-17 1
3 2-3-17 2
3 2-4-17 3
3 2-5-17 1
如果分组将按user_id和日期之间相距+/- 3天进行分组,则通过val求和的组应该是这样的:
user_id date sum(val)
1 1-2-17 3
2 1-2-17 2
2 1-10-17 1
3 1-1-17 1
3 2-1-17 8
我不确定最后一个日期是否会显示为2-1-17,但我们的想法是将3天内的所有日期分组在一起。
这是否可能以一种优雅的方式使用Grouper
,resample
或其他Pandas或Python日期函数?
您可以将groupby
与自定义组一起使用:
# convert to datetime
s = pd.to_datetime(df['date'], dayfirst=False)
# set up groups of consecutive dates within ± 3 days
group = (s.groupby(df['user_id'])
.apply(lambda s: s.diff().abs().gt('3days').cumsum())
)
# group by ID and new group and aggregate
out = (df.groupby(['user_id', group], as_index=False)
.agg({'date': 'last', 'val': 'sum'})
)
输出:
user_id date val
0 1 1-2-17 3
1 2 1-2-17 2
2 2 1-10-17 1
3 3 1-1-17 1
4 3 2-5-17 8
中间体(为清晰起见按user_id
排序):
user_id date val datetime diff abs >3days cumsum
0 1 1-1-17 1 2017-01-01 NaT NaT False 0
3 1 1-1-17 1 2017-01-01 0 days 0 days False 0
4 1 1-2-17 1 2017-01-02 1 days 1 days False 0
1 2 1-1-17 1 2017-01-01 NaT NaT False 0
5 2 1-2-17 1 2017-01-02 1 days 1 days False 0
6 2 1-10-17 1 2017-01-10 8 days 8 days True 1
2 3 1-1-17 1 2017-01-01 NaT NaT False 0
7 3 2-1-17 1 2017-02-01 31 days 31 days True 1
8 3 2-2-17 1 2017-02-02 1 days 1 days False 1
9 3 2-3-17 2 2017-02-03 1 days 1 days False 1
10 3 2-4-17 3 2017-02-04 1 days 1 days False 1
11 3 2-5-17 1 2017-02-05 1 days 1 days False 1