I am trying to get the cumulative sum of a variable (v) for groups (\"a\" and \"b\") within a dataframe. How can I get the result at the bottom -- whose rows are even number
split<-
is a pretty weird beast
split(d$cs, d$g) <- lapply(split(d$v, d$g), cumsum)
leading to
> d
g v cs
1 a 1 1
2 b 4 4
3 a 1 2
4 b 4 8
5 a 1 3
6 b 4 12
7 a 2 5
8 b 8 20
9 a 2 7
10 b 8 28
11 a 2 9
12 b 8 36
I would use ave
. If you look at the source of ave
, you'll see it essentially wraps Martin Morgan's solution.
R> g <- factor(c("a","b","a","b","a","b","a","b","a","b","a","b"))
R> v <- c(1,4,1,4,1,4,2,8,2,8,2,8)
R> d <- data.frame(g,v)
R> d$cs <- ave(v, g, FUN=cumsum)
R> d
g v cs
1 a 1 1
2 b 4 4
3 a 1 2
4 b 4 8
5 a 1 3
6 b 4 12
7 a 2 5
8 b 8 20
9 a 2 7
10 b 8 28
11 a 2 9
12 b 8 36
> library(nlme)
> g <- factor(c("a","b","a","b","a","b","a","b","a","b","a","b"))
> v <- c(1,4,1,4,1,4,2,8,2,8,2,8)
> cs <- rep(0,12)
> d <- data.frame(g,v,cs)
> d <- d[order(d$g),]
> temp <- by(d$v,d$g,cumsum)
> d$cs <- do.call("c",temp)
> d
g v cs
1 a 1 1
3 a 1 2
5 a 1 3
7 a 2 5
9 a 2 7
11 a 2 9
2 b 4 4
4 b 4 8
6 b 4 12
8 b 8 20
10 b 8 28
12 b 8 36
Another solution using the by function, but I had to order the data first
My tool of choice for these things is the plyr package:
require(plyr)
> ddply(d,.(g),transform,cs = cumsum(v))
g v cs
1 a 1 1
2 a 1 2
3 a 1 3
4 a 2 5
5 a 2 7
6 a 2 9
7 b 4 4
8 b 4 8
9 b 4 12
10 b 8 20
11 b 8 28
12 b 8 36