尝试计算2个日期之间的案例数,有表包含数字和时间间隔,我想创建包含日期和案例总和的输出表。容易(和解决)的问题是:
df <- data.frame(person = c("A", "B", "C"), start = c("2014-01-01", "2014-01-03", "2014-01-04"), stop = c("2014-01-02", "2014-01-06", "2014-01-04") )
df
f1 = function() { #keeping dates
as.data.frame(table(unlist(apply(df[-1], 1,
function(x) as.character(seq(as.Date(x[1], "%Y-%m-%d"),
as.Date(x[2], "%Y-%m-%d"), "1 day"))))))}
f1()
它会返回
Var1 Freq
1 2014-01-01 1
2 2014-01-02 1
3 2014-01-03 1
4 2014-01-04 2
5 2014-01-05 1
6 2014-01-06 1
我需要的是总结第一列,使用像这样的输入数据
df <- data.frame(cases = c(5, 2, 2), start = c("2014-01-01", "2014-01-03", "2014-01-04"), stop = c("2014-01-02", "2014-01-06", "2014-01-04") )
它应该返回
Var1 cases
1 2014-01-01 5
2 2014-01-02 5
3 2014-01-03 2
4 2014-01-04 4
5 2014-01-05 2
6 2014-01-06 2
也许甚至不会是不公开的情况,我可以用什么来计算每天的病例数?如果日期在开始和结束之间有效但数据中没有任何出现,有没有办法显示0值
修改
Aichao的回答是我所需要的 - 唯一遗漏的是获得0总和,例如
df <- data.frame(cases = c(5, 2, 2),
start = c("2014-01-01", "2014-01-04", "2014-01-04"),
stop = c("2014-01-02", "2014-01-06", "2014-01-04") )
获取
Var1 x
1 2014-01-01 5
2 2014-01-02 5
3 2014-01-03 0
4 2014-01-04 4
5 2014-01-05 2
6 2014-01-06 2
答案 0 :(得分:1)
这是一个与您使用f1
:
f2 <- function(df) {
df2 <- do.call(rbind, lapply(1:nrow(df), function(i) {
Var1 <- as.character(seq(as.Date(df$start[i],format="%Y-%m-%d"),
as.Date(df$stop[i],format="%Y-%m-%d"),"day"))
cases <- rep(df$cases[i],length(Var1))
data.frame(Var1,cases)
}))
aggregate(df2[,-1], by=list(Var1=df2[,1]), FUN=sum)
}
在f2
:
df2
中的每一行,从df$start
到df$stop
的日期序列构建数据框df
。在这里,lapply
用于循环df
的每一行,并且每行的cases
重复以匹配生成的日期序列的length
。然后使用rbind
按行组合每个数据框。aggregate
(来自stats
个包裹)此df2
按日期(即Var1
)和sum
向上cases
。 使用您的数据:
f2(df)
## Var1 x
##1 2014-01-01 5
##2 2014-01-02 5
##3 2014-01-03 2
##4 2014-01-04 4
##5 2014-01-05 2
##6 2014-01-06 2
使用0
作为cases
填写缺失日期的一种方法是从上述解决方案中获取汇总结果,并创建跨越日期范围的新日期序列。这将为新输出创建Var1
列。然后,将案例从旧结果复制到与日期匹配的新输出:
f2 <- function(df) {
df2 <- do.call(rbind, lapply(1:nrow(df), function(i) {
## note that we do not convert to characters here because we want to use these later to form the sequence
Var1 <- seq(as.Date(df$start[i],format="%Y-%m-%d"),
as.Date(df$stop[i],format="%Y-%m-%d"),"day")
cases <- rep(df$cases[i],length(Var1))
data.frame(Var1,cases)
}))
df2 <- aggregate(df2[,-1], by=list(Var1=df2[,1]), FUN=sum)
## sort previous result by date
df2 <- df2[order(df2[,1]),]
## create new sequence spanning range
Var1 <- as.character(seq(df2[1,1],df2[nrow(df2),1],"day"))
## create cases of zeros matching Var1 in length
cases <- rep(0,length(Var1))
## copy over cases from previous result that matches date
cases[na.omit(match(as.character(df2[,1]),Var1))] <- df2[,2]
## output as data frame
data.frame(Var1,cases)
}
在您更新的数据上:
f2(df)
## Var1 cases
##1 2014-01-01 5
##2 2014-01-02 5
##3 2014-01-03 0
##4 2014-01-04 4
##5 2014-01-05 2
##6 2014-01-06 2