【发布时间】:2019-04-12 07:07:20
【问题描述】:
我正在开发一个基于tidyverse 的数据工作流,并且遇到了一种情况,即我的数据框具有很多时间间隔。我们称数据框为my_time_intervals,可以这样复现:
library(tidyverse)
library(lubridate)
my_time_intervals <- tribble(
~id, ~group, ~start_time, ~end_time,
1L, 1L, ymd_hms("2018-04-12 11:15:03"), ymd_hms("2018-05-14 02:32:10"),
2L, 1L, ymd_hms("2018-07-04 02:53:20"), ymd_hms("2018-07-14 18:09:01"),
3L, 1L, ymd_hms("2018-05-07 13:02:04"), ymd_hms("2018-05-23 08:13:06"),
4L, 2L, ymd_hms("2018-02-28 17:43:29"), ymd_hms("2018-04-20 03:48:40"),
5L, 2L, ymd_hms("2018-04-20 01:19:52"), ymd_hms("2018-08-12 12:56:37"),
6L, 2L, ymd_hms("2018-04-18 20:47:22"), ymd_hms("2018-04-19 16:07:29"),
7L, 2L, ymd_hms("2018-10-02 14:08:03"), ymd_hms("2018-11-08 00:01:23"),
8L, 3L, ymd_hms("2018-03-11 22:30:51"), ymd_hms("2018-10-20 21:01:42")
)
这是同一数据框的tibble 视图:
> my_time_intervals
# A tibble: 8 x 4
id group start_time end_time
<int> <int> <dttm> <dttm>
1 1 1 2018-04-12 11:15:03 2018-05-14 02:32:10
2 2 1 2018-07-04 02:53:20 2018-07-14 18:09:01
3 3 1 2018-05-07 13:02:04 2018-05-23 08:13:06
4 4 2 2018-02-28 17:43:29 2018-04-20 03:48:40
5 5 2 2018-04-20 01:19:52 2018-08-12 12:56:37
6 6 2 2018-04-18 20:47:22 2018-04-19 16:07:29
7 7 2 2018-10-02 14:08:03 2018-11-08 00:01:23
8 8 3 2018-03-11 22:30:51 2018-10-20 21:01:42
关于my_time_intervals的几点说明:
-
数据通过
group变量分为三组。 -
id变量只是数据框中每一行的唯一 ID。 -
时间间隔的开始和结束以
lubridate形式存储在start_time和end_time中。 -
有些时间间隔重叠,有些不重叠,而且它们总是不按顺序排列。例如,
1行与3行重叠,但它们都不与2行重叠。 -
两个以上的区间可能会相互重叠,有些区间完全落在其他区间内。在
group == 2中查看行4到6。
我想要的是在每个group 中,将任何重叠的时间间隔折叠成连续的间隔。在这种情况下,我想要的结果如下所示:
# A tibble: 5 x 4
id group start_time end_time
<int> <int> <dttm> <dttm>
1 1 1 2018-04-12 11:15:03 2018-05-23 08:13:06
2 2 1 2018-07-04 02:53:20 2018-07-14 18:09:01
3 4 2 2018-02-28 17:43:29 2018-08-12 12:56:37
4 7 2 2018-10-02 14:08:03 2018-11-08 00:01:23
5 8 3 2018-03-11 22:30:51 2018-10-20 21:01:42
请注意,重叠在不同groups之间的时间间隔不合并。另外,我现在不关心id 列会发生什么。
我知道lubridate 包包含与区间相关的函数,但我不知道如何将它们应用到这个用例中。
我怎样才能做到这一点?
【问题讨论】:
-
my_time_intervals %>% group_by(group) %>% arrange(start_time) %>% mutate(indx = c(0, cumsum(as.numeric(lead(start_time)) > cummax(as.numeric(end_time)))[-n()])) %>% group_by(group, indx) %>% summarise(start_time = first(start_time), end_time = last(end_time)) %>% select(-indx) -
感谢@Masoud 的建议。我不确定代码是什么意思,但我试过了,结果与问题中我想要的输出不匹配(我会将不正确的输出与您的代码一起附加到问题中,以便您查看)。你能解释一下你的代码是做什么的吗?谢谢!
-
你错过了
arrange。效果很好。
标签: r dataframe datetime tidyverse lubridate