3

Possible Duplicate:
How to ddply() without sorting?

I have the following data frame

dd1 = data.frame(cond = c("D","A","C","B","A","B","D","C"), val = c(11,7,9,4,3,0,5,2))
dd1
  cond val
1    D  11
2    A   7
3    C   9
4    B   4
5    A   3
6    B   0
7    D   5
8    C   2

and now need to compute cumulative sums respecting the factor level in cond. The results should look like that:

> dd2 = data.frame(cond = c("D","A","C","B","A","B","D","C"), val = c(11,7,9,4,3,0,5,2), cumsum=c(11,7,9,4,10,4,16,11))
> dd2
  cond val cumsum
1    D  11     11
2    A   7      7
3    C   9      9
4    B   4      4
5    A   3     10
6    B   0      4
7    D   5     16
8    C   2     11

It is important to receive the result data frame in the same order as the input data frame because there are other variables bound to that.

I tried ddply(dd1, .(cond), summarize, cumsum = cumsum(val)) but it didn't produce the result I expected.

Thanks

Community
  • 1
  • 1
behas
  • 3,386
  • 5
  • 27
  • 27

3 Answers3

8

Use ave instead.

dd1$cumsum <- ave(dd1$val, dd1$cond, FUN=cumsum)
Joshua Ulrich
  • 173,410
  • 32
  • 338
  • 418
3

If doing this by hand is an option then split() and unsplit() with a suitable lapply() inbetween will do this for you.

dds <- split(dd1, dd1$cond)
dds <- lapply(dds, function(x) transform(x, cumsum = cumsum(x$val)))
unsplit(dds, dd1$cond)

The last line gives

> unsplit(dds, dd1$cond)
  cond val cumsum
1    D  11     11
2    A   7      7
3    C   9      9
4    B   4      4
5    A   3     10
6    B   0      4
7    D   5     16
8    C   2     11

I separated the three steps, but these could be strung together or placed in a function if you are doing a lot of this.

Gavin Simpson
  • 170,508
  • 25
  • 396
  • 453
3

A data.table solution:

require(data.table)
dt <- data.frame(dd1)
dt[, c.val := cumsum(val),by=cond]
> dt
#    cond val c.val
# 1:    D  11    11
# 2:    A   7     7
# 3:    C   9     9
# 4:    B   4     4
# 5:    A   3    10
# 6:    B   0     4
# 7:    D   5    16
# 8:    C   2    11
Arun
  • 116,683
  • 26
  • 284
  • 387