Calculate cumsum from the end towards the beginning
An option without explicitly reversing the vector:
ave(ts$val, ts$var, FUN = function(x) Reduce(sum, x, right = TRUE, accumulate = TRUE))
[1] 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 1 1 1 0 0 0 0 0 0 0
Or the same approach with dplyr
:
ts %>%
group_by(var) %>%
mutate(val = Reduce(sum, val, right = TRUE, accumulate = TRUE))
Promoting my comment to an answer; using:
ts$val2 <- ave(ts$val, ts$var, FUN = function(x) rev(cumsum(rev(x))))
gives:
> ts var val val2 1 a 0 2 2 a 0 2 3 a 0 2 4 a 0 2 5 a 1 2 6 a 0 1 7 a 0 1 8 a 0 1 9 a 0 1 10 a 1 1 11 a 0 0 12 a 0 0 13 a 0 0 14 a 0 0 15 a 0 0 16 b 0 2 17 b 0 2 18 b 0 2 19 b 0 2 20 b 1 2 21 b 0 1 22 b 0 1 23 b 1 1 24 b 0 0 25 b 0 0 26 b 0 0 27 b 0 0 28 b 0 0 29 b 0 0 30 b 0 0
Or with dplyr
or data.table
:
library(dplyr)
ts %>%
group_by(var) %>%
mutate(val2 = rev(cumsum(rev(val))))
library(data.table)
setDT(ts)[, val2 := rev(cumsum(rev(val))), by = var]