Blog de Estadística & R Software

Blog de Máxima Formación dedicado a Estadística aplicada con R Software
Tamaño de fuente: +

Cómo calcular resúmenes por grupo rápidamente

¿Sabes cómo calcular resúmenes estadísticos rápidos sin necesidad de utilizar bucles o crear funciones propias? o ¿cómo hacer para que estos resúmenes se calculen en cada grupo de datos por separado?


En R tenemos varias funciones que nos permiten repetir una misma tarea sobre unos objetos sin la necesidad de tener que escribir un bucle ni crear una función.

En una única línea de código y de manera más eficiente!

Por ejemplo, podemos pedirle a R que calcule la media de todas las columnas de nuestra base de datos en una única línea de comando.

Hoy veremos la familia de funciones "apply", la función "by", "aggregate", "ddlyr" y "summaryBy".


¿Cómo trabajan estas funciones?

Pues, cada una se aplica para objetos distintos (vectores, data frames, matrices, listas, etc.) y nos dan un resultado en un formato distinto.

(Casi) todo en R es un objeto, pero... ¡existen distintos tipos de objetos!

Tipos de objetos: 

  • vectores (un conjunto de elementos del mismo tipo) o factores (si está formado por categorías -categórico-). Por ejemplo, x={hombre, mujer}
  • conjuntos de vectores en 2D llamados matrices o data frames (si la matriz tiene datos de distinto tipo -numéricos y categóricos-), Por ejemplo, una matriz donde en las filas tenemos la respuesta de cada sujeto y en las columnas las preguntas que se le hicieron.
  • conjuntos de vectores en más de 2D llamados arrays. Si en el ejemplo anterior tenemos una matriz de datos para cada comunidad autónoma, entonces podemos construir un array.
  • o listas (lista de varios tipos de elementos). Si además de las matrices de datos agregamos "metadata", es decir, información como la fecha de la toma de la muestra, etc.






Entonces, según qué tipo de objeto de entrada (argumento) y salida vayamos a utilizar, podemos elegir entre distintas funciones para realizar nuestros resúmenes estadísticos.

En la siguiente tabla puedes ver un resumen de las principales funciones,  luego veremos su aplicación en R.



¿Qué función elegir para resumir nuestros datos?


FAMILIA "APPLY"

La familia de funciones "apply" se diferencian según el tipo de datos de entrada y el resultado de su aplicación del siguiente modo:

Veamos algunos ejemplos con los datos "iris":

> str(iris)
'data.frame': 150 obs. of 5 variables:
$ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
$ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
$ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
$ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
$ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 …


APPLY

  • "apply" se utiliza cuando queremos aplicar una función a las filas o columnas de una matriz o data frame (odimensión de un array); generalmente no funciona para data frames a no ser que se transforme a matriz previamente.
> apply(iris[,-5],2,mean)
Sepal.Length Sepal.Width Petal.Length Petal.Width
5.843333 3.057333 3.758000 1.199333
> apply(iris[,-5], 2, fivenum)
Sepal.Length Sepal.Width Petal.Length Petal.Width
[1,] 4.3 2.0 1.00 0.1
[2,] 5.1 2.8 1.60 0.3
[3,] 5.8 3.0 4.35 1.3
[4,] 6.4 3.3 5.10 1.8
[5,] 7.9 4.4 6.90 2.5


SAPPLY

  • "sapply" se utiliza cuando queremos aplicar una función a cada elemento de una lista o data frame y obtener unvector, matriz o una lista simplificado como resultado.
> sapply(iris[,-5], mean)
Sepal.Length Sepal.Width Petal.Length Petal.Width
5.843333 3.057333 3.758000 1.199333
> sapply(iris[,-5], fivenum)
Sepal.Length Sepal.Width Petal.Length Petal.Width
[1,] 4.3 2.0 1.00 0.1
[2,] 5.1 2.8 1.60 0.3
[3,] 5.8 3.0 4.35 1.3
[4,] 6.4 3.3 5.10 1.8
[5,] 7.9 4.4 6.90 2.5


LAPPLY

  • "lapply" se utiliza cuando queremos aplicar una función a cada elemento de una lista y obtener otra lista como resultado.
> lapply(iris[,-5],mean)
$Sepal.Length
[1] 5.843333
$Sepal.Width
[1] 3.057333
$Petal.Length
[1] 3.758
$Petal.Width
[1] 1.199333
> lapply(iris[,-5], fivenum)
$Sepal.Length
[1] 4.3 5.1 5.8 6.4 7.9
$Sepal.Width
[1] 2.0 2.8 3.0 3.3 4.4
$Petal.Length
[1] 1.00 1.60 4.35 5.10 6.90
$Petal.Width
[1] 0.1 0.3 1.3 1.8 2.5


TAPPLY

  • "tapply" se utiliza cuando queremos aplicar una función a subconjuntos de un vector (estos subconjuntos se definen con un vector o factor) y obtener un vector como resultado.
> tapply(iris$Petal.Length, iris$Species, mean)
setosa versicolor virginica
1.462 4.260 5.552


OTRAS

  • "vapply" es similares a las dos anteriores pero podemos decirle a R qué tipo de objeto queremos como resultado.
> vapply(iris[,-5], fivenum, c(Min.=0, "1st Qu."=0, Median=0, "3rd Qu."=0, Max.=0))
Sepal.Length Sepal.Width Petal.Length Petal.Width
Min. 4.3 2.0 1.00 0.1
1st Qu. 5.1 2.8 1.60 0.3
Median 5.8 3.0 4.35 1.3
3rd Qu. 6.4 3.3 5.10 1.8
Max. 7.9 4.4 6.90 2.5
  • "mapply" se utiliza cuando queremos aplicar una función a varios tipos de estructuras (e.g. vectores, listas), a sus primeros elementos, luego a los segundos, etc. y obtener como resultado un vector o array.
  • "rapply" se utiliza cuando queremos aplicar una función a cada elemento de un objeto con estructura de lista anidada (una lista dentro de una lista), de manera recursiva.



Las funciones "by" y "aggregate".


Ambas son similares a "tapply" pero con algunas pequeñas diferencias, veámoslas!


BY

La diferencia entre "by" y "tapply" es:

1) la clase de resultado, porque "by" devuelve una lista.

2) algunas peculiaridades respecto al tamaño de los objetos.


> tapply(iris$Sepal.Width , iris$Species , mean )
setosa versicolor virginica
3.428 2.770 2.974
>
> by(iris$Sepal.Width , iris$Species , mean )
iris$Species: setosa
[1] 3.428
-------------------------------------------------------
iris$Species: versicolor
[1] 2.77
-------------------------------------------------------
iris$Species: virginica
[1] 2.974

3) La función "by" funciona también cuando el tamaño de los 2 primeros argumentos son distintos, cuestión no resuelta por tapply.

 tapply(iris, iris$Species, summary )
Error in tapply(iris, iris$Species, summary):
arguments must have same length


AGGREGATE

La función "aggregate" también se comporta de manera similar a "tapply" aunque:

1) el segundo argumento de "aggregate" debe ser una lista, mientras que para "tapply" puede ser una lista o no.

2) y el resultado es de clase distinta, para "aggregate" el resultado es un "data frame" mientras que para tapply es un "array":

> tapply(iris$Sepal.Length , iris$Species , mean) 
setosa versicolor virginica
5.006 5.936 6.588
> aggregate(iris$Sepal.Length , list(iris$Species), mean)
Group.1 x
1 setosa 5.006
2 versicolor 5.936
3 virginica 6.588

3) La función "aggregate" también tiene la ventaja de la opción "subset" que permite seleccionar un subconjunto de datos.

4) La función "aggregate" es más sencilla de utilizar porque permite el formato de fórmula:

> aggregate(Sepal.Length ~ Species, data = iris, mean)
Species Sepal.Length
1 setosa 5.006
2 versicolor 5.936
3 virginica 6.588



DOS FUNCIONES AÚN MÁS SENCILLAS

Además de aggregate, by y tapply, podemos utilizar 2 funciones más rápidas para realizar cálculos por grupos incluso utilizando fórmulas! 

Estas funciones se encuentran en paquetes extra de R (no en los que vienen instalados por defecto, como ocurre en las funicones anteriores) son: 

  • ddplyr (del paquete plyr) y 
  • summaryBy (del paquete doBy).


DDPLYR

La función "ddply" del paquete "plyr" permite aplicar una función a un data frame para cada subconjunto de datos que le indiquemos y combinar los resultados en otro data frame (además sirve para dividir un conjunto de datos)

> library(plyr)
> ddply(iris, "Species", colwise(mean))
Species Sepal.Length Sepal.Width Petal.Length Petal.Width
1 setosa 5.006 3.428 1.462 0.246
2 versicolor 5.936 2.770 4.260 1.326
3 virginica 6.588 2.974 5.552 2.026
> ddply(iris, "Species",summarise,N=length(iris$Sepal.Length),mean=mean(iris$Sepal.Length),sd=sd(iris$Sepal.Length))
Species N mean sd
1 setosa 150 5.843333 0.8280661
2 versicolor 150 5.843333 0.8280661
3 virginica 150 5.843333 0.8280661


SUMMARYBY

La función "summaryBy" del paquete "doBy" nos permite calcular resúmenes estadísticos por grupo utilizando un formato de fórmula.

> summaryBy(Sepal.Length + Sepal.Width + Petal.Length + Petal.Width ~ Species, data=iris, FUN=mean)
Species Sepal.Length.mean Sepal.Width.mean Petal.Length.mean
1 setosa 5.006 3.428 1.462
2 versicolor 5.936 2.770 4.260
3 virginica 6.588 2.974 5.552
Petal.Width.mean
1 0.246
2 1.326
3 2.026
> summaryBy(Sepal.Length ~ Species, data=iris, FUN=c(mean,sd))
Species Sepal.Length.mean Sepal.Length.sd
1 setosa 5.006 0.3524897
2 versicolor 5.936 0.5161711
3 virginica 6.588 0.6358796

También existe:

  • summarize() en el paquete Hmisc



Espero que estos atajos para los cálculos te hayan gustado y te ahorren mucho tiempo, saludos!

Valora este artículo del blog:
Análisis multivariado para Big Data
Podemos cambiar las estadísticas
 

Comentarios (0)

Rated 0 out of 5 based on 0 votes
There are no comments posted here yet

Deja tus comentarios

Posting comment as a guest.
Archivos adjuntos (0 / 3)
Share Your Location
Escribe el texto que se muestra en la siguiente imagen. ¿No lo ves claro?

Únete a nuestra comunidad