Reputation: 491
I want to use the data.table
functions to update a column's value by referring the value its value in previous rows. Here is an example
> DT<-data.table(id=1:2,x=1:10,y=1)
I already knew data.table
can refer to previous rows in a way like below:
> 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
However, the next example is not working, where trying to create a Fibonacci
series using previous values in column y
to update itself. It seems data.table is not using a loop to perform the calculation iteratively. Can anyone tell me how to solve this kind problem using data.table
elegantly?
> 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
What I actually want is below (column y
is updated):
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
Upvotes: 2
Views: 887
Reputation: 24178
Generating Fibonacci numbers is by definition a sequential problem, which we could solve in data.table
by defining a custom function that works with a for.loop
under the hood.
# 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
Upvotes: 6