¡Auxilio! ¿Cómo hago gráficos en R? (Parte 2)
En este post vamos a ver los distintos tipos de gráficos que podemos hacer con R base según la información que necesitemos transmitir.
Bienvenidas y bienvenidos a la cuarta entrega de esta saga titulada Cómo analizar datos cuantitativos sin morir en el intento. En entregas previas vimos cómo empezar a ver nuestros datos en RStudio, cómo calcular medidas básicas de estadística descriptiva y cómo generar gráficos automáticos. En este post vamos a profundizar un poco más en los tipos de gráficos que podemos hacer, ya no de forma automática, sino en función del tipo de información que queremos transmitir.
La visualización de datos es hoy en día un tema bastante importante tanto en el mundo de la ciencia de datos como en la comunicación científica. Si bien parece que hay tantas opiniones como personas que las generan, mi postura es que un buen gráfico no siempre es el más llamativo o complejo, sino aquel que más se adecua al contexto comunicativo y el que más nos facilita la vida. Hay ámbitos sociales donde se valoran los gráficos por su capacidad de presentar varias dimensiones de un fenómeno en poco espacio, como en el mundo de las infografías, pero hay otros donde el gráfico es un complemento de otro tipo de información, como un artículo científico. Este contexto va a definir qué tanta información tendremos que condensar en el gráfico y cuánto tiempo podemos dedicarle.
Existen muchos paquetes de R que proveen herramientas muy poderosas y complejas para generar gráficos, como el rey indiscutido {ggplot2} o {plotly}. Sin embargo, cuando estamos empezamos a aprender a programar en R esas herramientas complejas se convierten en salvavidas de plomo, no solamente por la amplísima variedad de opciones, sino también porque la curva de aprendizaje se vuelve un poco empinada. Es por esto que acá nos vamos a concentrar en los gráficos que podemos hacer con R base y poniendo el foco siempre en lo que queremos transmitir, más que en el gráfico en sí.
Primer paso: ¿cómo pensar un gráfico?
Al igual que en los posts anteriores, vamos a trabajar con los datos de pingüinos:
# install.packages("datos")
library(datos)
pinguinos <- pinguinos
En el post anterior vimos una forma intuitiva de empezar a graficar los datos, gracias a la función plot()
que evalúa las variables que elegimos y en función de eso decide qué tipo de gráfico hacer. Esto viene bien cuando estamos empezando y estamos en una etapa exploratoria de los datos. Sin embargo, en una investigación real, vamos a empezar a definir preguntas que queremos que los datos nos respondan; a veces esas preguntas son previas a los datos y tienen que ver con el diseño de la investigación y a veces esas preguntas surgen de la misma exploración. En estos posteos no vamos a profundizar en metodología de investigación, pero podés leer más sobre el tema acá.
En general, lo recomendable es partir de una pregunta de investigación y luego pensar qué gráfico nos puede aportar esa respuesta. Sin embargo, para poder llegar a esa instancia tenemos que ya conocer previamente qué tipos de gráficos existen para poder darnos cuenta de cuál es el que necesitamos. Solo por ese motivo este posteo va a estar organizado en función de los tipos de gráficos, en lugar de enfocarnos en las preguntas.
La gran mayoría de los gráficos tienen dos ejes, el X (horizontal) y el Y (vertical); esto significa que en principio podemos pensar en que el gráfico nos muestra cómo se relacionan dos variables o dos aspectos de nuestros datos. Ese es el punto de partida, siempre: queremos ver algo (un eje) en función de otro algo (otro eje). Por convención se suele tomar el eje X como la variable independiente (es decir, lo que está dado) y el eje Y como la variable dependiente o resultado (es decir, lo que va a cambiar en función de esa variable independiente). Luego, sobre esa base vamos a poder complejizar la información y especificar otros cruces.
Finalmente, otro aspecto a tener en cuenta es que el tipo de variable que tengamos va a restringir los distintos tipos de gráficos que podamos elegir. Esto quiere decir que las variables numéricas y las categóricas, por ejemplo, darán lugar a distintos gráficos (podés explorar un poco más acá). Yo sé, yo sé que te está pareciendo mucha información, pero te aseguro que muchas de estas cuestiones se van a ir volviendo intuitivas con el tiempo. ¡Empecemos!
El histograma
El histograma es uno de los gráficos menos frecuentes en los artículos académicos pero al mismo tiempo más importante en prácticamente todo lo que hacemos en estadística. Básicamente es un gráfico que muestra cómo se distribuye una variable en el conjunto de datos que forma nuestra muestra. Toma una sola variable numérica y especifica cuántos elementos de la muestra tienen un valor particular. Por ejemplo:
hist(pinguinos$largo_pico_mm)
Este gráfico nos muestra en el eje X los valores que puede tomar el largo del pico de los pingüinos de la muestra y en el eje Y la cantidad de pingüinos cuyos picos tienen ese largo. Vemos entonces que parece haber dos grandes grupos: el primero con picos entre 30 y 43 mm, y el segundo entre 43 y 60mm. Este gráfico nos permite ver qué valores de largo de pico son más frecuentes (alrededor de 40 y alrededor de 50) y cuáles son poco frecuentes (menos de 35 y más de 55).
Si lo pensamos visualmente, vemos que un histograma es un conjunto de barras que marcan cantidades. El ancho de cada barra representa un intervalo dentro de las longitudes posibles, pero en este caso no muestra un valor preciso. De hecho, podemos modificar a mano la cantidad de barras que tendrá el histograma con el argumento breaks
:
hist(pinguinos$largo_pico_mm, breaks = 5)
En este caso redujimos la cantidad de barras respecto a la versión anterior y el resultado es bien distinto: si bien vemos con más detalle que los 35mm es un valor de quiebre importante y que la mayoría de los pingüinos tienen picos entre 45 y 50mm de largo, perdimos la precisión y la sensibilidad respecto a los grupos. De hecho, en el post anterior vimos que el vínculo entre el largo y el alto del pico mostraba tres grupos diferenciados, por lo cual sería lógico esperar ver algo así en este gráfico. Podemos probar con otros valores de barras:
hist(pinguinos$largo_pico_mm, breaks = 50)
hist(pinguinos$largo_pico_mm, breaks = 100)
hist(pinguinos$largo_pico_mm, breaks = 200)
A medida que aumentamos la cantidad de barras, nos acercamos a una barra por pingüino, que tal vez no es lo más interesante ni necesario, porque ya en 50 empezamos a notar la diferenciación entre grupos. A veces es cuestión de probar qué cantidad de barras es la más adecuada para lo que queremos graficar.
Encontramos entonces que hay tres grandes grupos según los cuales varía la longitud del pico. Revisamos nuestros datos y vemos que hay tres especies de pingüinos: Adelia, Barbijo y Papúa, entonces nos preguntamos si la longitud de los picos puede deberse a eso. Por suerte, tenemos un gráfico que nos puede ayudar: el gráfico de barras.
El gráfico de barras
Este debe ser el gráfico más frecuente en el mundo de la visualización de datos. Algunas personas lo menosprecian por su simplicidad, pero la verdad es que puede ser muy útil y fácil de leer (aunque tiene algunos sesgos, como veremos más adelante). Entonces, quiero saber si el largo de los picos varía en función de la especie de pingüinos. Para eso, antes necesito calcular las medias para cada una de las especies. Recordarán que en el post anterior usamos la función aggregate
; el problema es que el resultado es un objeto que no podemos usar fácilmente para graficar. Podemos usar la función tapply
que básicamente hace lo siguiente: sobre el objeto X
, aplicá la función FUN
a partir de los grupos generados por INDEX
1. Y a esa tabla, le aplicamos la función barplot()
para generar el gráfico de barras:
barplot(tapply(X = pinguinos$largo_pico_mm,
INDEX = pinguinos$especie,
FUN = mean, na.rm = TRUE))
Los lenguajes de programación permiten este tipo de recursividad (una cosa adentro de otra) con mucha facilidad, siempre y cuando el objeto que genere la primera función (tapply()
) sea un objeto que la segunda función (barplot()
) pueda tomar. De todos modos, para nosotras personas de carne y hueso algo así puede volverse un poco difícil de leer; una alternativa es dividir esto en dos pasos, primero crear un objeto con las medias y luego graficar el objeto:
# primero creamos la tabla
tabla_medias <- tapply(X = pinguinos$largo_pico_mm,
INDEX = pinguinos$especie,
FUN = mean, na.rm = TRUE)
# luego graficamos la tabla a partir del objeto
barplot(tabla_medias)
El resultado es el mismo. En general yo no soy muy amiga de crear muchos objetos intermedios que después no voy a volver a utilizar, porque considero que da lugar a confusiones, pero es cierto que ayuda a que el código sea fácil de leer.
Volvamos al gráfico. Tal como vimos en el post anterior podemos agregarle al gráfico un título o modificar las etiquetas de los ejes. Más allá de eso, hay algo que debería haberte llamado la atención: si mirás la regla del eje Y, vas a ver que se corta en 40. ¿Por qué? No lo sé, a veces ocurre. Podemos corregirlo especificando un argumento llamado ylim
que lo que hace es definir los límites numéricos entre los cuales se extiende el gráfico. Al ser dos valores, los debemos concatenar con la función c()
:
barplot(tapply(X = pinguinos$largo_pico_mm,
INDEX = pinguinos$especie,
FUN = mean, na.rm = TRUE),
ylim = c(0, 55))
Bien, vemos entonces que hay algunas diferencias entre el largo del pico de los pingüinos en función de las especies, sobre todo entre Adelia y Barbijo. Sin embargo, graficar medias de esta forma tiene un sesgo del cual hablamos anteriormente: la media es una medida muy sensible a valores extremos y al mismo tiempo los esconde, porque no permite ver la variación existente (que sabemos que existe, porque la vimos en el histograma). Para eso tenemos otro gráfico: el boxplot o gráfico de cajas y bigotes (sí, juro que se traduce así).
Gráfico de cajas y bigotes (boxplot)
Me disculparán mis compatriotas, pero me voy a quedar con el nombre en inglés. El boxplot es un tipo de gráfico que representa de forma directa las siguientes medidas estadísticas: mediana, cuartiles, rango intercuartil y datos atípicos (también llamados outliers). Pueden leer un poco más sobre este tipo de gráfico en su sitio de Wikipedia, pero lo más importante es que nos permite ver la dispersión de los datos. Veamos:
boxplot(pinguinos$largo_pico_mm)
En un boxplot tenemos que identificar en primer lugar dos cosas: la caja central y las líneas externas (los bigotes). El valor indicado por el inicio de la caja indica el primer cuartil, es decir, el 25% de los datos; luego, la línea oscura indica la mediana (el 50% de los datos); finalmente, el borde superior de la caja marca el 75% de los datos. A su vez, los bigotes se extienden para alcanzar hasta 1,5 el rango intercuartílico, que es la diferencia entre el tercer y el primer cuartil de la distribución. Todos aquellos valores que sean más altos o más bajos que ese rango, serán considerados valores atípicos.
Si todavía no te dormiste con esa explicación (o al revés, si te pareció difícil de entender), lo que quiero que te lleves es esto: un boxplot te muestra qué tan dispersa es la muestra. Si la caja se ve compactada y los bigotes son cortos, significa que la mayoría de los datos están condensados en valores cercanos. En cambio, un boxplot con cajas y bigotes extensos muestra una distribución con mayor variación.
Podemos separar los boxplots con nuestras variables categóricas:
boxplot(pinguinos$largo_pico_mm ~ pinguinos$sexo)
Para marcar grupos usamos el símbolo ~
denominado virgulilla, muy frecuente a la hora de definir fórmulas. En la amplia mayoría de las funciones en R, podés leer la fórmula como A en función de B, entonces en este caso sería el largo de los picos en función de su sexo. El gráfico muestra eso: la dispersión de los largos de los picos según si el pingüino es macho o hembra. Lo que vemos es que hay dimorfismo sexual: las hembras tienden a tener un pico más corto que los machos. Podemos ver aún más variedad si dividimos esta variable en función de la especie:
boxplot(pinguinos$largo_pico_mm ~ pinguinos$especie)
Acá vemos que las especies Barbijo y Papúa tienden a tener picos de longitudes parecidas (los primeros un poco más largos que los segundos), mientras que los pingüinos Adelia tienen picos bastante más cortos que los demás. También podemos ver un punto en el caso de los pingüinos Adelia: ese punto representa un caso (un pingüino) cuya longitud de pico excede 1,5 veces el rango intercuartílico (es decir, está bastante lejos de la mediana); esto es considerado un valor atípico.
El boxplot es un gráfico que viene bien para pensar en conjunto con el histograma; si bien transmiten información similar, el boxplot es un poco más complejo y puede servir para precisar algunas intuiciones que podamos tener a partir del histograma2.
Cierre
En este post vimos tres gráficos clásicos en el mundo de la investigación: el histograma, el gráfico de barras y el boxplot. Con estos gráficos vas a poder entender un poco más cómo funcionan tus datos. 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.
La función
tapply
forma parte de las funciones derivadas deapply
; podés leer más sobre ellas aquí.↩︎El boxplot también tiene sesgos, es decir, puede esconder diferencias. Podés revisar este post para ver cómo distintas distribuciones podrían mostrar un mismo boxplot y qué opciones (avanzadas) existen para resolverlo.↩︎