使用Pandas按日期范围(timedelta)分组



这个问题以前就有人问过,但我想进一步讨论。因为我没有足够的经验值,所以我无法评论这个问题,所以我重新发布了下面的链接,后面跟着我的评论:

使用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

最新更新