2012-04-19 16 views
12

Questo è meglio illustrato con un esempioStatistiche riassuntive di due o più variabili fattore?

str(mtcars) 
mtcars$gear <- factor(mtcars$gear, labels=c("three","four","five")) 
mtcars$cyl <- factor(mtcars$cyl, labels=c("four","six","eight")) 
mtcars$am <- factor(mtcars$am, labels=c("manual","auto") 
str(mtcars) 
tapply(mtcars$mpg, mtcars$gear, sum) 

Questo mi dà la mpg sommati per ogni marcia. Ma diciamo che volevo un tavolo 3x3 con ingranaggi nella parte superiore e cilindri in basso, e 9 celle con le somme bivariate, come potrei ottenerlo 'elegantemente'.

Potrei andare.

tapply(mtcars$mpg[mtcars$cyl=="four"], mtcars$gear[mtcars$cyl=="four"], sum) 
tapply(mtcars$mpg[mtcars$cyl=="six"], mtcars$gear[mtcars$cyl=="six"], sum) 
tapply(mtcars$mpg[mtcars$cyl=="eight"], mtcars$gear[mtcars$cyl=="eight"], sum) 

Questo sembra ingombrante.

Quindi come potrei inserire una terza variabile nel mix?

Questo è un po 'nello spazio a cui sto pensando. Summary statistics using ddply

aggiornamento Questo mi porta lì, ma non è carino.

aggregate(mpg ~ am+cyl+gear, mtcars,sum) 

Acclamazioni

risposta

32

Come su questo, che utilizzano ancora tapply()? È più versatile di quanto sapessi!

with(mtcars, tapply(mpg, list(cyl, gear), sum)) 
#  three four five 
# four 21.5 215.4 56.4 
# six 39.5 79.0 19.7 
# eight 180.6 NA 30.8 

Oppure, se si desidera l'output di stampa di essere un po 'più interpretabile:

with(mtcars, tapply(mpg, list("Cylinder#"=cyl, "Gear#"=gear), sum)) 

Se si desidera utilizzare più di due variabili di cross-classificazione, l'idea è esattamente lo stesso. I risultati saranno poi restituite in un array 3-o-più-dimensionale:

A <- with(mtcars, tapply(mpg, list(cyl, gear, carb), sum)) 

dim(A) 
# [1] 3 3 6 
lapply(1:6, function(i) A[,,i]) # To convert results to a list of matrices 

# But eventually, the curse of dimensionality will begin to kick in... 
table(is.na(A)) 
# FALSE TRUE 
# 12 42 
+0

Questa sembra essere la risposta ovvia, considerando che il primo passo è stato quello di sfruttare un fattore. il 'ftable' potrebbe anche essere di interesse. –

3

mi piace la risposta di Josh per questo, ma reshape2 può anche fornire un bel quadro di riferimento per questo tipo di problemi:

library(reshape2) 

#use subset to only grab the variables of interest... 
mtcars.m <- melt(subset(mtcars, select = c("mpg", "gear", "cyl")), measure.vars="mpg") 
#cast into appropriate format 
dcast(mtcars.m, cyl ~ gear, fun.aggregate=sum, value.var="value") 

    cyl three four five 
1 four 21.5 215.4 56.4 
2 six 39.5 79.0 19.7 
3 eight 180.6 0.0 30.8 
+0

Ho modificato per mettere le virgolette intorno a "" mpg "' passato a 'measure.vars', b/c il codice non funzionava altrimenti per me. Ti sembra giusto anche a te? Inoltre, c'è un modo semplice per ottenere questo per restituire 'NA' piuttosto che' 0' nel mezzo della riga in basso? –

+0

@ JoshO'Brien - molto strano, non ho idea del perché abbia funzionato in precedenza senza virgolette intorno a mpg ... grazie per quello. Inoltre, il parametro 'fill' su' dcast' dovrebbe consentire a NA, ma sto ottenendo uno strano errore ... l'impostazione 'fill = Inf' o qualsiasi altro valore numerico funziona comunque. Questo non è quello che mi aspetterei dalla funzione ... scaverà ulteriormente – Chase

5

Penso che le risposte già a questa domanda siano fantastiche opzioni, ma volevo condividere un'opzione aggiuntiva basata sul pacchetto dplyr (questo mi è venuto in mente perché sto insegnando un corso proprio ora dove usiamo dplyr per la manipolazione dei dati, quindi volevo evitare di introdurre gli studenti a funzioni R di base specializzate come tapply o aggregate).

È possibile raggruppare quante più variabili si desidera utilizzando la funzione group_by e quindi riepilogare le informazioni da questi gruppi con summarize. Credo che questo codice è più leggibile per un nuovo arrivato R rispetto all'interfaccia formula a base di aggregate, ottenendo risultati identici:

library(dplyr) 
mtcars %>% 
    group_by(am, cyl, gear) %>% 
    summarize(mpg=sum(mpg)) 
#  am cyl gear mpg 
# (dbl) (dbl) (dbl) (dbl) 
# 1  0  4  3 21.5 
# 2  0  4  4 47.2 
# 3  0  6  3 39.5 
# 4  0  6  4 37.0 
# 5  0  8  3 180.6 
# 6  1  4  4 168.2 
# 7  1  4  5 56.4 
# 8  1  6  4 42.0 
# 9  1  6  5 19.7 
# 10  1  8  5 30.8 

Con due variabili, si può riassumere con una variabile nelle righe e l'altra sulle colonne aggiungendo una chiamata alla funzione spread dal pacchetto tidyr:

library(dplyr) 
library(tidyr) 
mtcars %>% 
    group_by(cyl, gear) %>% 
    summarize(mpg=sum(mpg)) %>% 
    spread(gear, mpg) 
#  cyl  3  4  5 
# (dbl) (dbl) (dbl) (dbl) 
# 1  4 21.5 215.4 56.4 
# 2  6 39.5 79.0 19.7 
# 3  8 180.6 NA 30.8 
0

la risposta contiene stessa uscita utilizzando Tapply e funzione di aggregazione.

Vorrei aggiungere alcune informazioni alla risposta di Josh O'Brien. L'utente può utilizzare la funzione di aggregazione o sfruttare in base all'output. Per usare più di una variabile fattore in tapply si può usare il metodo mostrato da Josh.

caricamento di dati

data("mtcars") 

Uso Tapply

with(mtcars, tapply(mpg, list("Cylinder#"=cyl, "Gear#"=gear), sum)) 

L'output del codice precedente è

 Gear# 
Cylinder#  3  4 5 
    4  21.5 215.4 56.4 
    6  39.5 79.0 19.7 
    8 180.6 NA 30.8 

Uso funzione di aggregazione

with(mtcars, aggregate(mpg, list(Cylinder = cyl, Gear = gear), sum)) 

uscita della funzione di aggregazione

Cylinder Gear x 
1  4 3 21.5 
2  6 3 39.5 
3  8 3 180.6 
4  4 4 215.4 
5  6 4 79.0 
6  4 5 56.4 
7  6 5 19.7 
8  8 5 30.8 

Ora, se l'utente vuole stesso output funzione di aggregazione ma utilizzando Tapply.

as.data.frame(as.table(with(mtcars, tapply(mpg, list("Cylinder#"=cyl, "Gear#"=gear), 
sum)))) 

uscita della funzione Tapply

Cylinder. Gear. Freq 
1   4  3 21.5 
2   6  3 39.5 
3   8  3 180.6 
4   4  4 215.4 
5   6  4 79.0 
6   8  4 NA 
7   4  5 56.4 
8   6  5 19.7 
9   8  5 30.8 

NA di può essere mantenuto o rimosso secondo i requisiti di business.