Calculate cumsum from the end towards the beginning

谁说我不能喝 提交于 2021-01-02 08:21:38

问题


I'm trying to calculate the cumsum starting from the last row towards the first for each group.

Sample data:

t1 <- data.frame(var = "a", val = c(0,0,0,0,1,0,0,0,0,1,0,0,0,0,0))
t2 <- data.frame(var = "b", val = c(0,0,0,0,1,0,0,1,0,0,0,0,0,0,0))
ts <- rbind(t1, t2)

Desired format (grouped by var):

ts <- data.frame(var = c("a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a",
                           "b", "b", "b", "b", "b", "b", "b", "b", "b", "b", "b", "b", "b", "b", "b"), 
                 val = c(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))

回答1:


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]



回答2:


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))


来源:https://stackoverflow.com/questions/50413415/calculate-cumsum-from-the-end-towards-the-beginning

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!