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函数,但是我无法绕过任何解决方案。 任何帮助表示赞赏!谢谢
答案 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)
如果您想按小组计算唯一天数,我会这样做(假设您的Start
和End
列采用日期格式):
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
解释:对于每一行,您可以使用Start
和End
日期创建日期序列。之后,您可以使用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")