R中分组行的折叠/合并日期范围

时间:2018-09-20 20:28:04

标签: r data.table

我有一个看起来像这样的数据框:

ID    Group    Start Date    End Date
1     A        2018-08-08    2018-08-09
1     A        2018-08-07    2018-08-08
1     A        2018-08-05    2018-08-07
1     B        2018-08-08    2018-08-09
1     B        2018-08-07    2018-08-08
2     A        2018-08-08    2018-08-09
2     A        2018-08-07    2018-08-08
2     A        2018-08-01    2018-08-07
2     B        2018-08-08    2018-08-09
2     B        2018-08-07    2018-08-08
3     B        2018-08-07    2018-08-08
4     B        2018-08-07    2018-08-08
4     B        2018-08-01    2018-08-07

我想折叠它,以便如果一行中的Start Date变量与下一行中的End Date变量相匹配,则这些行将按IDGroup个变量:

ID    Group    Start Date    End Date
1     A        2018-08-05    2018-08-09
1     B        2018-08-07    2018-08-09
2     A        2018-08-01    2018-08-09
2     B        2018-08-07    2018-08-09
3     B        2018-08-07    2018-08-08
4     B        2018-08-01    2018-08-08

在dplyr中,我知道可以通过类似以下操作来做到这一点:

df %>% 
group_by(ID, Group) %>%
rowwise() %>%
do(somefunction(x){})

但是我在编写函数时需要帮助。或者,如果有一个for循环或其他实现可以做到这一点,将不胜感激。

修改 为了更清楚起见,我已经修改了示例数据。

1 个答案:

答案 0 :(得分:-1)

我已经使用BioConducter的IRanges软件包找到了更灵活的解决方案。这对于不一定与邻居连续的情况非常有效:

source("http://bioconductor.org/biocLite.R")
biocLite("IRanges")
require(IRanges)
library(data.table)
library(lubridate)

setDT(df)

df[, , as.data.table(reduce(
       IRanges(as.numeric(`Start Date`),
               as.numeric(`End Date`)),
               min.gapwidth=1L))[, lapply(.SD, as_date), .SDcols = -"width"], 
                                 .(`ID`, `Group`)]

在上面的代码段中,我在每个日期范围内使用了reduce中的IRanges函数,该函数会将给定容差min.gapwidth中的相邻范围折叠起来。在这种情况下,我指定了日期范围(如果彼此之间在一天之内)(min.gapwidth=1L)。您可以将其设置为0L以合并严格连续的日期。

IRanges仅采用数字值,因此我将日期转换为数字,然后应用as_date包中的lubridate函数将其转换回日期。我还删除了width列,该列将告诉我每个范围内有多少天。