Apply a function to groups within a data.frame in R
apply, dataframe, r
Solution
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
Problem
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 numbered properly -- into column cs of my dataframe? ``` > 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 g v cs 1 a 1 0 2 b 4 0 3 a 1 0 4 b 4 0 5 a 1 0 6 b 4 0 7 a 2 0 8 b 8 0 9 a 2 0 10 b 8 0 11 a 2 0 12 b 8 0 > r=gapply(d,FUN="cumsum",form=~g, which="v") >r $a v 1 1 3 2 5 3 7 5 9 7 11 9 $b v 2 4 4 8 6 12 8 20 10 28 12 36 > str(r) List of 2 $ a:'data.frame': 6 obs. of 1 variable: ..$ v: num [1:6] 1 2 3 5 7 9 $ b:'data.frame': 6 obs. of 1 variable: ..$ v: num [1:6] 4 8 12 20 28 36 ``` I guess I could figure out some laborious way to get the data from those dataframes into d$cs, but there's got to be some easy tweak I'm missing.