5

我有一个如下所示的数据集:

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 循环之外还没有找到解决方案。)

提前致谢!

4

3 回答 3

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))))
于 2012-11-27T20:01:59.613 回答
0

以下内容对您有何帮助?

 indx <- which(data$id == c(data$id[-1], NA))
 data$date[indx] - data$date[indx+1]



这只是将id's 移动 1 并将它们与 id 进行比较以检查相邻匹配项。
然后对于 dat 减法,只需从后续行的日期中减去匹配项。

于 2012-11-27T21:14:31.060 回答
0

如果您需要更复杂的公式,您可以使用聚合:

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 答案中的排序顺序相同。

于 2012-11-28T03:01:21.947 回答