我有一个如下所示的数据集:
ID | DATE | SCORE
-------------------------
123 | 1/15/10 | 10
123 | 1/1/10 | 15
124 | 3/5/10 | 20
124 | 1/5/10 | 30
...
因此,要将上述代码段作为数据框加载,代码为:
id<-c(123,123,124,124)
date<-as.Date(c('2010-01-15','2010-01-01','2010-03-05','2010-01-05'))
score<-c(10,15,20,30)
data<-data.frame(id,date,score)
我正在尝试添加一列来计算“自此ID的最后一次记录以来的天数”。
现在我正在使用看起来像这样的FOR循环:
data$dayssincelast <- rep(NA, nrow(data))
for(i in 2:nrow(data)) {
if(data$id[i] == data$id[i-1])
data$dayssincelast[i] <- data$date[i] - data$date[i-1]
}
有没有更快的方法呢?(我看了一下APPLY,但除了FOR循环之外无法找到解决方案。)
提前致谢!
答案 0 :(得分:5)
如果您的日期在id
范围内,则此功能应该有效。
id<-c(123,123,124,124)
date<-as.Date(c('2010-01-15','2010-01-01','2010-03-05','2010-01-05'))
score<-c(10,15,20,30)
data<-data.frame(id,date,score)
data <- data[order(data$id,data$date),]
data$dayssincelast<-do.call(c,by(data$date,data$id,function(x) c(NA,diff(x))))
# Or, even more concisely
data$dayssincelast<-unlist(by(data$date,data$id,function(x) c(NA,diff(x))))
答案 1 :(得分:0)
以下内容如何为您服务?
indx <- which(data$id == c(data$id[-1], NA))
data$date[indx] - data$date[indx+1]
<小时/>
这只是将id
换算为1并将它们与id进行比较以检查相邻匹配。
然后对于dat减法,只需从后续行的日期中减去匹配。
答案 2 :(得分:0)
如果您需要更复杂的公式,可以使用aggregate:
a <- aggregate(date ~ id, data=data, FUN=function(x) c(NA,diff(x)))
data$dayssincelast <- c(t(a[-1]), recursive=TRUE) # Remove 'id' column
此处适用与@nograpes答案相同的排序顺序。