计算具有重叠和日期范围间隙的独特日期

时间:2016-05-12 19:36:42

标签: r date dplyr

Group       Start            End             Days
A           5/12/2015        5/14/2015       3
A           5/12/2015        5/14/2015       3
B           1/1/2015         1/3/2015        3
B           1/1/2015         1/3/2015        3
H           1/8/2015         1/9/2015        2
H           1/8/2015         1/9/2015        2
H           1/13/2015        1/15/2015       3
H           1/7/2015         1/17/2015       3
H           1/12/2015        1/22/2015       7

我上面附上了我的数据集示例。我正在尝试计算R中每个组的唯一天数。对于一些观察,它非常简单,即A和B.但是有些组具有不同的天数重叠以及日期范围中的间隙,即H. / p>

无论如何,我可以总结一下R中每个群体的唯一天数(没有重叠并说明差距)吗?即A和B将分别返回3天​​,H将返回11天。

Group   Count
A       3
B       3
H       16

我最好的猜测是使用dplyr和summaryrize函数,但是我无法绕过任何解决方案。 任何帮助表示赞赏!谢谢

2 个答案:

答案 0 :(得分:6)

这是一个dplyr解决方案:

library(dplyr)

df %>%
    group_by(Group,rn = row_number()) %>%
    do(data.frame(.,Date = seq(as.Date(.$Start,format = '%m/%d/%Y'),
                               as.Date(.$End,format = '%m/%d/%Y'),
                               '1 day'))) %>%
    group_by(Group) %>%
    summarise(numDays = n_distinct(Date))

我们的想法是创建一个新列,其中包含从开始到结束的日期序列,然后计算每个组中唯一观察的长度。

这给出了:

   Group numDays
  (fctr)   (int)
1      A       3
2      B       3
3      H      16

答案 1 :(得分:4)

如果您想按小组计算唯一天数,我会这样做(假设您的StartEnd列采用日期格式):

library(data.table)
setDT(mydf)[, .(dates = seq.Date(Start,End,'day')) , by = .(Group,1:nrow(mydf))
            ][, .(count = uniqueN(dates)), by = Group][]

给出:

   Group count
1:     A     3
2:     B     3
3:     H    16

解释:对于每一行,您可以使用StartEnd日期创建日期序列。之后,您可以使用uniqueN函数计算唯一天数。这比我的旧回答(见下文)要好,因为这会考虑到差距。

与您描述的所需输出相比,这为H组提供了更高的数字。但是,如果仔细查看数据,您会发现正确的数字为16

基础R的类似解决方案:

l <- mapply(seq.Date, mydf$Start, mydf$End, 1)
df2 <- data.frame(group = rep(mydf$Group,sapply(l,length)),
                  dates = unlist(l))
aggregate(dates ~ group, df2, function(x) length(unique(x)))

给出了类似的结果:

  group dates
1     A     3
2     B     3
3     H    16

如果您希望dates中的df2列采用日期格式,请使用as.Date(unlist(l), origin = '1970-01-01')代替unlist(l)

使用过的数据:

mydf <- structure(list(Group = c("A", "A", "B", "B", "H", "H", "H", "H", "H"), 
                       Start = structure(c(16567, 16567, 16436, 16436, 16443, 16443, 16448, 16442, 16447), class = "Date"), 
                       End = structure(c(16569, 16569, 16438, 16438, 16444, 16444, 16450, 16452, 16457), class = "Date"), 
                       Days = c(3L, 3L, 3L, 3L, 2L, 2L, 3L, 3L, 7L)), 
                  .Names = c("Group", "Start", "End", "Days"), row.names = c(NA, -9L), class = "data.frame")