在R data.table计算中使用前一行中的值

我想在一个data.table中创build一个新的列,根据一列的当前值和另一列的前一个值来计算。 是否有可能访问以前的行?

例如:

> DT <- data.table(A=1:5, B=1:5*10, C=1:5*100) > DT ABC 1: 1 10 100 2: 2 20 200 3: 3 30 300 4: 4 40 400 5: 5 50 500 > DT[, D := C + BPreviousRow] # What is the correct code here? 

正确的答案应该是

 > DT ABCD 1: 1 10 100 NA 2: 2 20 200 210 3: 3 30 300 320 4: 4 40 400 430 5: 5 50 500 540 

使用v1.9.6中实现的shift() ,这非常简单。

 DT[ , D := C + shift(B, 1L, type="lag")] # or equivalently, in this case, DT[ , D := C + shift(B)] 

来自NEWS :

  1. 新的函数shift()实现向量列表data.framesdata.tables的快速lead/lag 。 它需要一个type参数,可以是“滞后” (默认)或“领先” 。 它可以非常方便地使用以及:=set() 。 例如: DT[, (cols) := shift(.SD, 1L), by=id] 。 请看看?shift更多的信息。

查看以前的答案历史。

有几个人回答了具体的问题。 请参阅下面的代码,了解在这种情况下可能会有所帮助的通用function。 而不是仅仅获得前一行,您可以随意select“过去”或“未来”中的行数。

 rowShift <- function(x, shiftLen = 1L) { r <- (1L + shiftLen):(length(x) + shiftLen) r[r<1] <- NA return(x[r]) } # Create column D by adding column C and the value from the previous row of column B: DT[, D := C + rowShift(B,-1)] # Get the Old Faithul eruption length from two events ago, and three events in the future: as.data.table(faithful)[1:5,list(eruptLengthCurrent=eruptions, eruptLengthTwoPrior=rowShift(eruptions,-2), eruptLengthThreeFuture=rowShift(eruptions,3))] ## eruptLengthCurrent eruptLengthTwoPrior eruptLengthThreeFuture ##1: 3.600 NA 2.283 ##2: 1.800 NA 4.533 ##3: 3.333 3.600 NA ##4: 2.283 1.800 NA ##5: 4.533 3.333 NA 

根据上面的@Steve Lianoglou的评论,为什么不只是:

 DT[, D:= C + c(NA, B[.I - 1]) ] # ABCD # 1: 1 10 100 NA # 2: 2 20 200 210 # 3: 3 30 300 320 # 4: 4 40 400 430 # 5: 5 50 500 540 

并避免使用seq_lenhead或任何其他function。

使用dplyr你可以这样做:

 mutate(DT, D = lag(B) + C) 

这使:

 # ABCD #1: 1 10 100 NA #2: 2 20 200 210 #3: 3 30 300 320 #4: 4 40 400 430 #5: 5 50 500 540 

遵循Arun的解决scheme,可以获得类似的结果而不用参考.N

 > DT[, D := C + c(NA, head(B, -1))][] ABCD 1: 1 10 100 NA 2: 2 20 200 210 3: 3 30 300 320 4: 4 40 400 430 5: 5 50 500 540 

我添加了一个填充参数,并更改了一些名称,并将其称为shifthttps://github.com/geneorama/geneorama/blob/master/R/shift.R