2012-04-19 7 views
12

Esto se ilustra mejor con un ejemplo¿Estadísticas de resumen por dos o más variables de factor?

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) 

Eso me da la mpg resumió por engranajes. Pero digamos que quería una mesa de 3x3 con equipo en la parte superior y cyl en el costado, y 9 celdas con las sumas bivariadas, ¿cómo lo conseguiría 'inteligentemente'?

Podría ir.

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) 

Esto parece engorroso.

Entonces, ¿cómo podría traer una tercera variable en la mezcla?

Esto es algo en el espacio en el que estoy pensando. Summary statistics using ddply

actualización Esto me lleva allí, pero no es bonito.

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

Saludos

Respuesta

32

¿Qué hay de esto, aún utilizando tapply()? ¡Es más versátil de lo que creías!

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 

O, si desea la salida impresa a ser un poco más interpretable:

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

Si desea utilizar más de dos variables cruzadas clasificación, la idea es exactamente lo mismo. Los resultados entonces se devuelven en una matriz de 3-o-más-dimensional:

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

Esto parece ser la respuesta obvia, teniendo en cuenta que el punto de partida fue un solo factor. 'ftable' también podría ser de interés. –

3

me gusta la respuesta de Josh para esto, pero reshape2 también pueden proporcionar un buen marco para este tipo de problemas:

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

Lo edité para poner comillas alrededor del '" mpg "' pasado a 'measure.vars', b/c el código no estaba funcionando para mí. ¿Te parece bien a ti también? Además, ¿hay alguna manera fácil de hacer que esto devuelva 'NA' en lugar de' 0' en el medio de la fila inferior? –

+0

@ JoshO'Brien - muy extraño, no tengo idea de por qué funcionó anteriormente sin comillas en mpg ... gracias por eso. Además, el parámetro 'fill' para' dcast' debería permitir NA's, pero estoy obteniendo un error extraño ... sin embargo, ajuste 'fill = Inf' o cualquier otro valor numérico. Esto no es lo que esperaría de la función ... profundizará aún más – Chase

5

Creo que las respuestas a esta pregunta son fantásticas opciones, pero quería compartir una opción adicional basada en el paquete dplyr (esto surgió porque enseño una clase en este momento donde usamos dplyr para la manipulación de datos, así que quería evitar introducir estudiantes a funciones R especializadas como tapply o aggregate).

Puede agrupar tantas variables como desee utilizando la función group_by y luego resumir la información de estos grupos con summarize. Creo que este código es más legible a un recién llegado R de la interfaz basada en la fórmula de aggregate, produciendo resultados idénticos:

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 dos variables, se puede resumir con una variable en las filas y la otra en las columnas mediante la adición de una llamada a la función spread del paquete 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 respuesta contiene misma salida utilizando tapply y función de agregado.

Me gustaría agregar algo de información a la respuesta de Josh O'Brien. El usuario puede usar la función de agregado o tapply dependiendo de la salida. Para usar más de una variable de factor en tapply uno puede usar el método que Josh ha mostrado.

Cargando conjunto de datos

data("mtcars") 

Usando tapply

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

La salida del código anterior es

 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 

Usando función de agregado

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

salida de la función agregada

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 

Ahora bien, si el usuario desea misma salida que la función de agregado, pero utilizando tapply.

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

salida de la función 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 

AN puede mantenerse o eliminarse de acuerdo con los requerimientos del negocio.

Cuestiones relacionadas