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

Cor*_*one 72 r data.table

我想在data.table中创建一个新列,该列根据一列的当前值和另一列的前一列计算得出.是否可以访问以前的行?

例如:

> DT <- data.table(A=1:5, B=1:5*10, C=1:5*100)
> DT
   A  B   C
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?
Run Code Online (Sandbox Code Playgroud)

应该是正确的答案

> DT
   A  B   C   D
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
Run Code Online (Sandbox Code Playgroud)

Aru*_*run 95

随着shift()中实现v1.9.6,这是非常简单的.

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

来自新闻:

  1. 新函数shift()快速实现lead/lagvector,list,data.framesdata.tables.它需要一个type可以是"滞后"(默认)或"前导"的参数.它可以非常方便地使用:=set().例如:DT[, (cols) := shift(.SD, 1L), by=id].请查看?shift更多信息.

查看以前答案的历史记录.

  • @SlowLearner:您可能还会发现`.I`很有用,它保存了curren组中行的行索引. (7认同)
  • 使用seq_len(.N - 1)而不是1 :(.N-1).这避免了与1:0相关的问题. (7认同)

Ste*_*pré 28

使用dplyr你可以做:

mutate(DT, D = lag(B) + C)
Run Code Online (Sandbox Code Playgroud)

这使:

#   A  B   C   D
#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
Run Code Online (Sandbox Code Playgroud)

  • 被低估的答案-感谢您的分享。 (2认同)

dnl*_*rky 20

有几个人回答了具体问题.请参阅下面的代码,了解我在这种情况下使用的通用功能可能会有所帮助.您可以根据需要在"过去"或"未来"中输入尽可能多的行,而不仅仅是获取前一行.

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
Run Code Online (Sandbox Code Playgroud)


Gar*_*man 12

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

DT[, D:= C + c(NA, B[.I - 1]) ]
#    A  B   C   D
# 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
Run Code Online (Sandbox Code Playgroud)

并避免使用seq_lenhead任何其他功能.

  • 很好 - 但是如果你想在一个组中找到前一个,这将不起作用. (2认同)

Ryo*_*ogi 9

遵循Arun的解决方案,可以在不参考的情况下获得类似的结果 .N

> DT[, D := C + c(NA, head(B, -1))][]
   A  B   C   D
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
Run Code Online (Sandbox Code Playgroud)