2012-05-18 17 views
13

Estoy tratando de obtener la suma acumulada de una variable (v) para grupos ("a" y "b") dentro de un marco de datos. ¿Cómo puedo obtener el resultado en la parte inferior, cuyas filas están incluso numeradas correctamente, en la columna cs de mi marco de datos?Aplicar una función a grupos dentro de un data.frame en R

> 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 

supongo que podría buscar la manera laboriosa para obtener los datos de esas tramas de datos en d $ cs, pero no tiene que haber algún truco fácil que me falta.

Respuesta

10

me gustaría utilizar ave. Si nos fijamos en el origen de ave, verá que esencialmente se ajusta al solution de Martin Morgan.

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 
+0

Siempre me olvido de 'ave'; aunque es lo mismo que vienen los otros 2? –

+0

@TylerRinker: es esencialmente lo mismo que la solución de Martin (ver mi edición). –

+0

Estaba confundido b/c comparado con el de joran. Olvidé que plyr reorganiza las cosas. +1 –

7

Mi herramienta de elección para estas cosas es la plyr paquete:

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 
13

split<- es una bestia bastante raro

split(d$cs, d$g) <- lapply(split(d$v, d$g), cumsum) 

conduce a

> 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 
+3

que fue dividido '<-. Default'. No me di cuenta de que existía (o que era la base para ave.) 'Split <-. Data.frame' es aún más extraño. –

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

Otra solución mediante el por función, pero tuve que pedir los datos del primer

Cuestiones relacionadas