60

I have the same question as this post, but I want to use dplyr:

With an R dataframe, eg:

df <- data.frame(id = rep(1:3, each = 5)
                 , hour = rep(1:5, 3)
                 , value = sample(1:15))

how do I add a cumulative sum column that matches the id?

Without dplyr the accepted solution of the previous post is:

df$csum <- ave(df$value, df$id, FUN=cumsum)
Community
  • 1
  • 1
Racing Tadpole
  • 4,270
  • 6
  • 37
  • 56

1 Answers1

94

Like this?

df <- data.frame(id = rep(1:3, each = 5),
                 hour = rep(1:5, 3),
                 value = sample(1:15))

mutate(group_by(df,id), csum=cumsum(value))

Or if you use the dplyr's piping operator:

df %>% group_by(id) %>% mutate(csum = cumsum(value))

Result in both cases:

Source: local data frame [15 x 4]
Groups: id

   id hour value csum
1   1    1     4      4
2   1    2    14     18
3   1    3     8     26
4   1    4     2     28
5   1    5     3     31
6   2    1    10     10
7   2    2     7     17
8   2    3     5     22
9   2    4    12     34
10  2    5     9     43
11  3    1     6      6
12  3    2    15     21
13  3    3     1     22
14  3    4    13     35
15  3    5    11     46
Stephen Henderson
  • 6,340
  • 3
  • 27
  • 33
  • 1
    Thanks. I guess to get the same output as the other approach, I'd need to finish with an `ungroup`? – Racing Tadpole Feb 16 '14 at 23:58
  • 3
    @RacingTadpole No. If you want the `cumsum` over the whole table just don't put in the `group_by` in the first place. – Stephen Henderson Sep 15 '15 at 11:36
  • 1
    I think the OP's question is if the `group_by` attribute sticks if you assign the result (`df <- df %>% group_by ...`), and the answer is that it does. If you don't follow with an `ungroup`, future operations on the reassigned `df` will act on the `id` column, which may not be what you want. – Wayne Feb 11 '19 at 15:47
  • 1
    Just make sure that `plyr` is not active in your session. Took me some time to figure it out: `dplyr::mutate(cumsum=cumsum(value))` – M. Beausoleil Mar 13 '19 at 15:40