¡Auxilio! Tengo datos cuantitativos, ¿y ahora qué hago? (Parte 2) | Macarena Quiroga

¡Auxilio! Tengo datos cuantitativos, ¿y ahora qué hago? (Parte 2)

Guía básica para empezar a trabajar con datos cuantitativos. En este post: media, mediana y moda con R

Imagen hecha por mí con el paquete {aRtsy}

Este post es la segunda entrega de la saga Cómo empezar a trabajar con datos cuantitativos sin que sea una tortura, pensada para gente que -como yo- tiene una formación en ciencias sociales o humanas y de golpe debe trabajar con datos numéricos o similar. En la primera entrega vimos cómo crear el entorno RStudio, cómo importar los datos y cómo inspeccionar la tabla de datos. En esta ocasión vamos a empezar a hablar de las tres medidas de tendencia central más importantes: la media, la mediana y la moda.


Antes de empezar, ¿qué es la estadística?

No, mentira. No vamos a ahondar en qué es la estadística por varios motivos: primero y principal porque no soy matemática, pero sobre todo porque hay mucho material en internet para profundizar en esas preguntas (empezando por la página de Wikipedia). Más allá de eso, sí me parece importante empezar por una diferencia clave: por un lado, tenemos la estadística descriptiva, cuyo objetivo es describir y resumir los datos disponibles, y por el otro la estadística inferencial que es la que se ocupa de generar modelos, inferencias y predicciones sobre los datos. Si bien hoy en día pareciera ser que lo más cool es hacer estadística inferencial, la verdad es que el primer paso obligatorio siempre es la descripción de los datos. Para poder explicar por qué los datos son así o predecir cómo se comportarían datos similares, primero tenemos que tener una idea clara de cómo son nuestros datos.

Dentro de la estadística descriptiva tenemos dos grandes áreas importantes: las medidas de tendencia central (el tema de este post) y las medidas de dispersión o variabilidad (lo veremos más adelante). Las tres medidas de tendencia central más importantes son las siguientes:

  • La media o promedio: cuando hablamos de media, en general nos referimos a la media aritmética, que no es lo mismo que la media ponderada o la media geométrica. Se calcula sumando todos los valores del conjunto y dividiéndolo por la cantidad de elementos.

  • La mediana: es el valor que está a la mitad del conjunto de datos cuando se los ordena de menor a mayor, es decir, el valor que deja por debajo a la mitad de los datos.

  • La moda: es el valor más frecuente en el conjunto de datos.

Todos estos valores transmiten diferente información sobre el conjunto de datos y tienen sus ventajas y desventajas. Ver sus resultados a la vez te va a ayudar a entender cómo son esos datos.


Media, mediana y moda con R

Vamos a trabajar con el paquete pinguinos, pero podés usar el conjunto de datos que necesites. Lo instalamos, cargamos y guardamos el conjunto de datos de pingüinos en un objeto, tal como hicimos en el post anterior:

install.packages("datos")
library(datos)
pinguinos <- pinguinos

Si ya instalaste el paquete, no tenés que instalarlo nuevamente. A veces queremos dejar líneas de código escritas en nuestro script pero no queremos ejecutarlas (por ejemplo, para tenerlas a mano o para no olvidarnos): en ese caso, podemos poner el símbolo # al comienzo de la línea. Esto se llama comentar una línea de código y es una forma tanto de evitar que se ejecuten comandos como de incorporar observaciones o comentarios para tu yo del futuro. Comentar o documentar tu código es una buena práctica para que tu yo del futuro entienda qué estabas pensando cuando escribiste cada cosa. Al principio puede parecer algo tedioso, pero creeme que lo vas a agradecer.

Por ejemplo, el bloque de código anterior se podría documentar de la siguiente forma:

# instalar el paquete
# install.packages("datos") 

# cargar el paquete
library(datos) 

# crear el objeto
pinguinos <- pinguinos 

Todo lo que está a la derecha del # no se ejecuta. Podés ubicarlo de esa forma o en una línea aparte. Ahí ya es un tema de gusto personal.

Bien, una vez que tenemos el objeto creado (te va a aparecer en el Environment, el panel que está en la esquina superior derecha), podés inspeccionarlo haciendo click en él o con la siguiente línea de código: View(pinguinos). En esta tabla tenemos tres variables categóricas (especie, isla, sexo) y cinco variables numéricas (largo y alto del pico, largo de la aleta, masa corporal y año de las mediciones).

Tomemos el largo del pico para calcular la media, la mediana y la moda. Para eso, vamos a usar funciones, que son las palabras que indican la acción que se debe ejecutar. De hecho, en el código anterior ya usamos otras funciones, como View(), install.packages() o library(). Las reconocés porque siempre tienen el set de paréntesis. Dentro de ese paréntesis se van a ubicar los elementos (o argumentos) sobre los cuales se va a ejecutar esa acción o las especificaciones de cómo queremos que se ejecute.

Para calcular la media vamos a usar la función mean(). Pero no es suficiente con especificar la tabla dentro de los paréntesis: tenemos que especificar también qué variable o columna queremos calcular. Esto se hace con el operador $, algo que se llama subsetting o creación de subconjuntos (podés leer más sobre métodos de subsetting aquí). Bien, lo ejecutamos (para ejecutar un comando, ubicás el cursor en esa línea y apretás control+enter o hacés click en Run arriba a la derecha del script).

mean(pinguinos$largo_pico_mm)
## [1] NA

Eh, ¡¿qué pasó?! Cuando ejecutamos ese comando, vemos que en la consola el resultado es NA, es decir Not Available. En otras palabras, esto significa que no se pudo calcular la media o que el resultado de la media es un valor faltante. Hay muchos motivos por los cuales una operación puede dar este resultado, pero por suerte en este caso el motivo es bastante simple: si inspeccionamos la tabla, vemos que en la fila 4 tenemos un NA como valor del largo del pico.

Si te acordás, en el post anterior vimos la función summary(), que devolvía un resumen de los estadísticos descriptivos de toda la tabla, entre los cuales estaba la cantidad de elementos faltantes en cada columna (también te devuelve las tres medidas que vamos a ver en este posteo, pero ignorémoslo). Vemos entonces que hay valores faltantes en casi todas las columnas, entonces tenemos que hacer algo.

Una de las alternativas es excluir del cálculo de la media aquellas observaciones (filas, pingüinitos) que no tengan el valor que queremos calcular, esto es, calcular la media de una forma especial. Muchas funciones permiten hacer especificaciones a la forma en la que se ejecutan: por ejemplo, por default la media se calcula con todos los valores de la columna, pero podemos especificar que no se tengan en cuenta los valores faltantes. Para saber si una función (en nuestro caso, mean()) se puede especificar, podemos escribir ?mean en la consola: eso nos muestra la documentación oficial de la función. Tengo el deber de advertirte que la documentación oficial no siempre es muy amable y fácil de entender, pero con el tiempo te vas acostumbrando.

Lo importante es que uno de los argumentos de la función, na.rm, permite especificar si queremos remover los valores NA, que es efectivamente nuestro caso. Para encender ese interruptor, lo que hacemos es agregar ese argumento a la función dentro de los paréntesis, separado por una coma (en este caso, el orden de los factores altera el producto, pero por el momento no vamos a profundizar demasiado para no complicarla):

mean(pinguinos$largo_pico_mm, na.rm = TRUE)
## [1] 43.92193

Ahora sí tenemos el valor de la media de largo del pico: 43.92193. Qué numero horrible, ¿no? Podemos redondear el valor con la función round() que lleva dos argumentos: el primero es el objeto a redondear (en nuestro caso, el cálculo de la media) y el segundo es la cantidad de decimales que queremos.

round(mean(pinguinos$largo_pico_mm, na.rm = TRUE), 2)
## [1] 43.92

Como verás, las funciones se pueden subordinar, en el sentido de que una función puede ser el argumento de otra. Esto se puede volver difícil de leer muy rápidamente, así que siempre recordá que las funciones en R se ejecutan de adentro hacia afuera (es decir, en el código anterior primero se ejecuta la media y sobre ese resultado se ejecuta el redondeo).

Bien, tenemos entonces que, en promedio, los picos de estos pingüinos miden 43,92mm. La media es un valor muy útil, pero una de sus grandes desventajas es que es un valor muy sensible a valores extremos. Pensalo de esta forma: si tengo una familia que gana $100 mensuales y otra que gana $1000, decir que las familias ganan en promedio $550 por mes es un número tramposo. Y esta artificialidad se puede dar incluso con una muestra más extensa: si tenemos 4 familias que ganan $100 mensuales y una familia que gana $1500, la media diría que las familias ganan en promedio $400 mensuales, que es cuatro veces lo que verdaderamente ganan las primeras cuatro familias.

Para evitar estos sesgos es que podemos usar las otras medidas de tendencia central para complementar nuestro análisis. La mediana ordena los valores de menor a mayor y busca cuál es el valor que está exactamente a la mitad:

median(pinguinos$largo_pico_mm, na.rm = TRUE)
## [1] 44.45

En este caso no es necesario redondear, porque no es el resultado de un cálculo, sino que es un valor específico. Vemos que el valor de la mediana (44.45) es levemente más alto que el valor de la media (43.92), pero no parece ser suficiente como para llamar la atención.

Ahora, quien sepa algo sobre el dimorfismo sexual podría preguntarse si el largo del pico es igual en los pingüinos macho y en las pingüinas hembras. Para eso, podemos calcular la mediana (o cualquier otra función) para los dos grupos por separado. Esto lo realizamos con la función aggregate(), cuyos argumentos son la columna que queremos calcular, luego la columna que divide las observaciones (que debe aparecer dentro de la función list() por motivos que no vienen al caso) y finalmente la función que queremos ejecutar.

aggregate(x = pinguinos$largo_pico_mm, by = list(pinguinos$sexo), FUN = median)
##   Group.1    x
## 1  hembra 42.8
## 2   macho 46.8

Vemos entonces que la mediana para hembras es 42.8, mientras que para machos es 46.8. Ahí ya empezamos a ver ciertas diferencias que podrían explicar la distancia entre la media y la mediana. ¿Será que hay en la tabla más datos de un sexo que del otro? Si volvemos a la tabla que nos devuelve summary() vemos que tenemos 168 registros de pingüinos machos y 165 de hembras, la diferencia es muy pequeña.

Finalmente, nos queda la última de las mediciones de tendencia central, la moda, que es el valor que más se repite en la tabla (el valor que está de moda, je). Acá nos enfrentamos con el siguiente problema, que en verdad no sabías que tenías. Hasta ahora estuvimos utilizando funciones de lo que se llama R base, es decir, el lenguaje de programación R sin ningún tipo de agregado. Sin embargo, como todo lenguaje de programación, en R existen distintos tipos de paquetes que proveen distintas funciones y objetos para distintos usos (de hecho, usamos un paquete para descargar nuestra base pinguinos, no sé si te acordarás). Pero aquí está el tema: en R base no hay ninguna función que permita calcular la moda (¿por qué? no lo sé). Entonces tenemos dos alternativas: o bien creamos nuestra propia función que calcule la moda, o bien podemos buscar un paquete que tenga esa función. Crear nuestras propias funciones es algo muy útil, pero definitivamente está por fuera del objetivo de estos posteos (aunque en el futuro, quién sabe).

Para buscar funciones podemos ir a sitios como RDocumentation y usar su buscador. Encontramos que existe el paquete statip que contiene la función mfv que permite calcular la moda. Lo instalamos con la función install.packages() y está listo para usar. En este caso, como solo nos interesa usar esa única función, no necesitamos cargar el paquete entero. Entonces, podemos usar el símbolo :: que se usa para indicar el origen de la función:

# install.packages("statip")
statip::mfv(pinguinos$largo_pico_mm, na_rm = TRUE)
## [1] 41.1
aggregate(x = pinguinos$largo_pico_mm, by = list(pinguinos$sexo), FUN = statip::mfv)
##   Group.1    x
## 1  hembra 46.5
## 2   macho 41.1

En este caso, la forma de remover los valores faltantes es con el argumento na_rm; esto se puede chequear con la documentación oficial (escribiendo ?mfv en la consola). Vemos entonces que el valor más frecuente de largo del pico es 41.1, bastante más bajo que la media y la mediana. Sin embargo, cuando lo calculamos por grupo, vemos que la moda de los machos es 46.5 y de los machos es 41.1. Bastante distinto a lo que daba la mediana, ¿no? Recordemos que en esta tabla hay otras agrupaciones que no estamos teniendo en cuenta, como la especie del pingüino y la isla donde habita. Es posible que esas otras variables de agrupación ayuden a entender estas diferencias. ¿Y saben qué ayuda mucho a entender estas cosas? Los gráficos. Pero esto es tema del siguiente posteo.


Cierre

En este post vimos tres medidas de tendencia central: media, mediana y moda. Además, vimos cómo especificar que no queremos tener en cuenta los valores faltantes y cómo realizar los cálculos desagregando por grupos. Finalmente, repasamos un poco cómo trabajar con paquetes. En el próximo post vamos a ver una función para empezar a realizar gráficos básicos.

Como siempre, recordá que podés suscribirte a mi blog para no perderte ninguna actualización, y si te quedó alguna consulta no dudes en contactarme. Y, si te gusta lo que hago, podés invitarme un cafecito desde Argentina o un kofi.

Macarena Quiroga
Macarena Quiroga
Lingüista/Becaria doctoral

Investigo la adquisición del lenguaje. Estudio estadística y ciencia de datos con R/Rstudio. Si te gusta lo que hago, podés invitarme un cafecito desde Argentina, o un kofi desde otros países. Suscribite a mi blog aquí.

Relacionado