2011-01-29 12 views
6

Supongamos que quisiera obtener algunas estadísticas de resumen en el conjunto de datos mtcars (parte de la base R versión 2.12.1). A continuación, agrupo los automóviles de acuerdo con la cantidad de cilindros del motor que tienen y tomo el medio por grupo de las variables restantes en mtcars.¿Cómo puedo generar estadísticas de resumen por grupo si mi variable de agrupación es un factor?

> str(mtcars) 
'data.frame': 32 obs. of 11 variables: 
$ mpg : num 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ... 
$ cyl : num 6 6 4 6 8 6 8 4 4 6 ... 
$ disp: num 160 160 108 258 360 ... 
$ hp : num 110 110 93 110 175 105 245 62 95 123 ... 
$ drat: num 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ... 
$ wt : num 2.62 2.88 2.32 3.21 3.44 ... 
$ qsec: num 16.5 17 18.6 19.4 17 ... 
$ vs : num 0 0 1 1 0 1 0 1 1 1 ... 
$ am : num 1 1 1 0 0 0 0 0 0 0 ... 
$ gear: num 4 4 4 3 3 3 3 4 4 4 ... 
$ carb: num 4 4 1 1 2 1 4 2 2 4 ... 
> ddply(mtcars, .(cyl), mean) 
     mpg cyl  disp  hp  drat  wt  qsec  vs  am  gear 
1 26.66364 4 105.1364 82.63636 4.070909 2.285727 19.13727 0.9090909 0.7272727 4.090909 
2 19.74286 6 183.3143 122.28571 3.585714 3.117143 17.97714 0.5714286 0.4285714 3.857143 
3 15.10000 8 353.1000 209.21429 3.229286 3.999214 16.77214 0.0000000 0.1428571 3.285714 
     carb 
1 1.545455 
2 3.428571 
3 3.500000 

Pero, si mi variable de agrupación es un factor, las cosas se vuelven más complicadas. ddply() arroja una advertencia para cada nivel del factor, ya que uno no puede tomar el mean() de un factor.

> mtcars$cyl <- as.factor(mtcars$cyl) 
> str(mtcars) 
'data.frame': 32 obs. of 11 variables: 
$ mpg : num 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ... 
$ cyl : Factor w/ 3 levels "4","6","8": 2 2 1 2 3 2 3 1 1 2 ... 
$ disp: num 160 160 108 258 360 ... 
$ hp : num 110 110 93 110 175 105 245 62 95 123 ... 
$ drat: num 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ... 
$ wt : num 2.62 2.88 2.32 3.21 3.44 ... 
$ qsec: num 16.5 17 18.6 19.4 17 ... 
$ vs : num 0 0 1 1 0 1 0 1 1 1 ... 
$ am : num 1 1 1 0 0 0 0 0 0 0 ... 
$ gear: num 4 4 4 3 3 3 3 4 4 4 ... 
$ carb: num 4 4 1 1 2 1 4 2 2 4 ... 
> ddply(mtcars, .(cyl), mean) 
     mpg cyl  disp  hp  drat  wt  qsec  vs  am  gear 
1 26.66364 NA 105.1364 82.63636 4.070909 2.285727 19.13727 0.9090909 0.7272727 4.090909 
2 19.74286 NA 183.3143 122.28571 3.585714 3.117143 17.97714 0.5714286 0.4285714 3.857143 
3 15.10000 NA 353.1000 209.21429 3.229286 3.999214 16.77214 0.0000000 0.1428571 3.285714 
     carb 
1 1.545455 
2 3.428571 
3 3.500000 
Warning messages: 
1: In mean.default(X[[2L]], ...) : 
    argument is not numeric or logical: returning NA 
2: In mean.default(X[[2L]], ...) : 
    argument is not numeric or logical: returning NA 
3: In mean.default(X[[2L]], ...) : 
    argument is not numeric or logical: returning NA 
> 

Por lo tanto, me pregunto si solo estoy tratando de generar estadísticas de resumen de la manera incorrecta.

¿Cómo se suelen generar estructuras de datos de estadísticas de resumen por grupo o por grupo (como medias, desviaciones estándar, etc.)? ¿Debo usar algo que no sea ddply()? Si puedo usar ddply(), ¿qué puedo hacer para evitar los errores que resultan al intentar tomar la media de mi factor de agrupamiento?

Respuesta

8

Use numcolwise(mean): la función numcolwise convierte su argumento (una función) en una función que opera solo en columnas numéricas (e ignora las columnas categóricas/factoriales).

> ddply(mtcars, .(cyl), numcolwise(mean)) 

     cyl  mpg  disp  hp  drat  wt  qsec  vs 
    1 4 26.66364 105.1364 82.63636 4.070909 2.285727 19.13727 0.9090909 
    2 6 19.74286 183.3143 122.28571 3.585714 3.117143 17.97714 0.5714286 
    3 8 15.10000 353.1000 209.21429 3.229286 3.999214 16.77214 0.0000000 
      am  gear  carb 
    1 0.7272727 4.090909 1.545455 
    2 0.4285714 3.857143 3.428571 
    3 0.1428571 3.285714 3.500000 
+1

Gracias Prasad! Tampoco me di cuenta en ese momento que podía usar una llamada 'aggregate()' en lugar de una llamada 'ddply()'. Por ejemplo: 'aggregate (cbind (hp, mpg) ~ cyl, data = mtcars, mean)'. – briandk

+0

¡Esa es una buena manera de hacerlo también! –

+0

Prasad, es un truco útil. –

2

No es una respuesta aquí, pero una observación. Esto no es un problema de ddply() per se. Mira este. La siguiente ambos funcionan bien para producir una tabla de medias:

aggregate(mtcars, by=list(mtcars$cyl), mean) 
apply(mtcars, 2, function(col) tapply(col, INDEX=mtcars$cyl, FUN=mean)) 

Pero después mtcars$cyl <- as.factor(mtcars$cyl) ninguno de los trabajos anteriormente, dado que R no sabe cómo tomar la media de una columna de factores. Podemos evitarlo mediante la eliminación de esa columna ("cilindros" es la columna 2) de las cosas pasaron a mean():

aggregate(mtcars[ , -2], by=list(mtcars$cyl), mean) 
apply(mtcars[ , -2], 2, function(col) tapply(col, INDEX=mtcars$cyl, FUN=mean)) 

Pero eso es bastante torpe.

+0

gracias! Lo intenté yo mismo, y tienes toda la razón: el problema es que R no sabe cómo tomar la media de un factor, y yo estaba luchando con formas de evitarlo. Tu manera definitivamente funciona, aunque 'aggregate()' te permite especificar qué columnas incluir también: 'aggregate (cbind (hp, mpg) ~ cyl, data = mtcars, mean)' – briandk

Cuestiones relacionadas