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

より複雑な数式が必要な場合は、集計を使用できます。

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 に答える