-1

I have a data.table as follows

set.seed(5)
x <- data.table(x=sample(1:20,15))

> x
     x
 1:  5
 2: 14
 3: 17
 4: 20
 5:  2
 6: 11
 7:  8
 8: 15
 9: 12
10: 16
11:  3
12: 18
13: 10
14:  4
15: 13

and I would like to start at 1 and cumulate values iteratively such that the value of cumsum() determines the next number to be added to the sum.

In the example I want to add the first value of x, here 5, then jump to value number 5 and add that, here 2, then jump to value number 5+2=7, here 8, then value number 5+2+8=15, here 13.

That is, I want to get a vector

> res
[1]  1  5  7 15

Has anyone any idea for this problem?

bumblebee
  • 1,116
  • 8
  • 20

3 Answers3

4

We can use Reduce with accumulate = TRUE

accum <- Reduce(function(i, j) i + x$x[i], x$x, accumulate = TRUE)
c(1, accum[!is.na(accum)])
# [1]  1  5  7 15 28

or purrr::accumulate

library(purrr)

accum <- accumulate(x$x, ~ .x + x$x[.x])
c(1, accum[!is.na(accum)])
# [1]  1  5  7 15 28
IceCreamToucan
  • 28,083
  • 2
  • 22
  • 38
  • the purrr-solution is considerably faster, in my case at least. Thanks! I wonder whether the solution can also be used when the incremental variable and the variable indexed are different. For example, starting from `x=1` the corresponding value of `y` is added and at `x=x1+y1` the corresponding value of `y` is added again and so on. Can't figure it out from the syntax. – bumblebee Feb 06 '19 at 17:38
  • If I'm understanding this new problem correctly you should be able to just replace `x$x` with the second vector (e.g. `y`) you want to use. So e.g. `x$x[.x]` replaced with `y[.x]` – IceCreamToucan Feb 06 '19 at 17:42
  • 1
    Almost correct — I meant a second vector within the data table, so `accumulate(x$y, ~ .x + x$y[.x])` then does the trick. Thanks, again! – bumblebee Feb 06 '19 at 17:56
2

A base R solution:

i = 1
v = i
sum = 0
while (i <= nrow(x)) {
   v = c(v, i)
   sum = sum + x$x[i]
   i = sum
}
Omry Atia
  • 2,411
  • 2
  • 14
  • 27
1

Here's a function that takes how long you want your vector to be and produces a vector of that length:

recursiveadd<-function(x, n) {k<-x$x[1]
 for (i in 1:(n-1)) {
     k[i+1]<-sum(x$x[k[i]],k[i])
   }
 k
}

recursiveadd(x,4)
[1]  5  7 15 28
iod
  • 7,412
  • 2
  • 17
  • 36