使用上一行更新列值

时间:2016-03-25 01:29:29

标签: r data.table

我想使用data.table函数通过在前面的行中引用其值来更新列的值。这是一个例子

> DT<-data.table(id=1:2,x=1:10,y=1)

我已经知道data.table可以通过以下方式引用之前的行:

> DT[,z:=cumsum(y),keyby=id]
> DT[]
    id  x y z
 1:  1  1 1 1
 2:  1  3 1 2
 3:  1  5 1 3
 4:  1  7 1 4
 5:  1  9 1 5
 6:  2  2 1 1
 7:  2  4 1 2
 8:  2  6 1 3
 9:  2  8 1 4
10:  2 10 1 5

但是,下一个示例无效,尝试使用列Fibonacci中的先前值创建y系列以更新自身。似乎data.table没有使用循环来迭代地执行计算。谁能告诉我如何使用data.table优雅地解决这类问题?

> DT[,y:=shift(y,1,fill=0)+shift(y,2,fill=0),]
> DT[]
    id  x y z
 1:  1  1 0 1
 2:  1  3 1 2
 3:  1  5 2 3
 4:  1  7 2 4
 5:  1  9 2 5
 6:  2  2 0 1
 7:  2  4 1 2
 8:  2  6 2 3
 9:  2  8 2 4
10:  2 10 2 5

我真正想要的是下面(列y已更新):

    id  x y z
 1:  1  1 1 1
 2:  1  3 1 2
 3:  1  5 2 3
 4:  1  7 3 4
 5:  1  9 5 5
 6:  2  2 1 1
 7:  2  4 1 2
 8:  2  6 2 3
 9:  2  8 3 4
10:  2 10 5 5

1 个答案:

答案 0 :(得分:5)

根据定义,生成Fibonacci数是一个连续问题,我们可以通过定义一个与data.table一起使用的自定义函数在for.loop中解决。

# Define function
fibon <- function(x) {
  for(i in 3:length(x)) x[i] = x[i-1] + x[i-2] 
  return(x)
}

# Plug into data.table
DT[,y := fibon(y), by = id]
> DT
#   id  x y z
#1:  1  1 1 1
#2:  1  3 1 2
#3:  1  5 2 3
#4:  1  7 3 4
#5:  1  9 5 5
#6:  2  2 1 1
#7:  2  4 1 2
#8:  2  6 2 3
#9:  2  8 3 4
#10: 2 10 5 5