2012-05-18 2 views
13

Sto cercando di ottenere la somma cumulativa di una variabile (v) per i gruppi ("a" e "b") all'interno di un dataframe. Come posso ottenere il risultato in fondo - le cui righe sono numerate correttamente - nella colonna cs del mio dataframe?Applicare una funzione ai gruppi all'interno di un data.frame in 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 

Credo che avrei potuto capire un modo laborioso per ottenere i dati da questi dataframes in d $ cs, ma ci deve essere qualche semplice ritocco mi manca.

risposta

10

userei ave. Se guardi la fonte di ave, vedrai che si tratta essenzialmente di solution di 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

Mi dimentico sempre di 'ave'; comunque è lo stesso che viene fuori come gli altri 2? –

+0

@TylerRinker: è essenzialmente la stessa della soluzione di Martin (vedi la mia modifica). –

+0

Ero confuso b/c rispetto a joran. Ho dimenticato che plyr riorganizza le cose. +1 –

7

Il mio strumento di scelta per queste cose è il plyr pacchetto:

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<- è un piuttosto strano bestia

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

che porta 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

che è stato diviso '<-. Default'. Non mi rendevo conto che esisteva (o che era la base per ave.) 'Split <-. Data.frame' è ancora più strano. –

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 

Un'altra soluzione utilizzando la per funzione, ma ho dovuto ordinare i dati prima