03C - Visualización de datos (personalización)

Si quieres correr este script localmente, debe haber descargado el proyecto, como se explica al comienzo del script 3A.

Como al principio de todo script, recomiendo reiniciar R. Esto lo conseguimos con Session > Restart R y clickeando en la escoba del panel de “Environment” (superior derecho).

Inicio: cargar paquetes, base de datos

library(tidyverse)

Cargar de datos: municipios

Carguemos nuestra base de datos en formato .rds. Tiene información comunal construida a partir de dos fuentes: la encuesta Casen 2017 y los resultados de las elecciones municipales del año 2016.

df_municipios <- read_rds("datos/datos_municipios.rds")

Gráfico de ejemplo

ggplot(data    = df_municipios,
       mapping = aes(x = as.factor(region),
                     y = porc_pobres_md4)) +
  geom_boxplot() +
  labs(x = "Región", y = "% Pobreza multidimensional",
       title   = "% de pobreza en las comunas de Chile, separadas por región",
       caption = "Fuente: Casen (2017)")

Gráficos como objetos / guardar gráficos en el disco

Podemos crear los gráficos como objetos en R. Hagamos esto para nuestro gráfico anterior:

p_pobreza_sep_region <- ggplot(data    = df_municipios,
                               mapping = aes(x = as.factor(region),
                                             y = porc_pobres_md4)) +
  geom_boxplot() +
  labs(x = "Región", y = "% Pobreza multidimensional",
       title = "% de pobreza en las comunas de Chile, separadas por región",
       caption = "Fuente: Casen (2017)")

Para generarlos, los llamamos en la consola:

p_pobreza_sep_region

Podemos continuar con cadenas de ggplot2 a partir de objetos:

p_pobreza_sep_region +
  geom_violin(alpha = 0.5)

También podemos guardar nuestros gráficos en el disco fácilmente, si es que son objetos:

ggsave(filename = "p_pobreza_sep_region.png",
       plot     = p_pobreza_sep_region)
## Saving 7 x 5 in image

¿Cómo conseguir que el gráfico tenga las proporciones que queremos? La mejor forma es modificando un poco algunos argumento de ggsave:

  • scale edita la proporción de tamaños entre el plano y los elementos del gráfico. Valores menores a 1 harán los elementos más grandes.

  • width edita el ancho, en pulgadas.

  • height edita el alto, en pulgadas.

  • Con units = "cm" podríamos dar ancho y alto en centímetros.

[Aquí hay una guía completa sobre guardar gráficos en disco, escrita por Jenny Bryan (2018)]

Casi siempre me funciona bien ocupar scale = 0.8, height = 6 y width = entre 8 y 10 (dependiendo si es un gráfico ancho o no). Hay mucho de ensayo y error aquí!

ggsave(filename = "p_pobreza_sep_region.png",
       plot     = p_pobreza_sep_region,
       scale = 0.8, height = 6, width = 10)

Personalización de gráficos

Etiquetas (labs)

Esto es algo que ya hemos visto, y se consigue con el comando labs():

ggplot(data    = df_municipios,
       mapping = aes(x = alcalde_coalicion)) +
  geom_bar() +
  labs(x = "Coalición del alcalde", y = "Frecuencia",
       title   = "Alcaldías por coalición, luego de las elecciones 2016",
       caption = "Fuente: Emol (2016)")

Algunos argumentos de labs() funcionan en cualquier gráfico (title, subtitle, caption, etc.), mientras otros dependen de los mapeos estéticos particulares de cada gráfico (x, y, color, shape, etc.).

Personalizar escalas numéricas

Volvamos a nuestro histograma de antes:

ggplot(data    = df_municipios,
       mapping = aes(x = porc_rural)) +
  geom_histogram(binwidth = 5, boundary = 0, closed = "left")  +
  labs(x = "% de población rural", y = "Frecuencia",
       title   = "Comunas chilenas según su porcentaje de población rural",
       caption = "Fuente: Casen (2017)")

Podemos editar arbitrariamente qué se muestra en los ejes continuos con los comandos scale_*_continuous() y el argumento breaks =:

ggplot(data    = df_municipios,
       mapping = aes(x = porc_rural)) +
  geom_histogram(binwidth = 5, boundary = 0, closed = "left")  +
  labs(x = "% de población rural", y = "Frecuencia",
       title   = "Comunas chilenas según su porcentaje de población rural",
       caption = "Fuente: Casen (2017)") +
  scale_x_continuous(breaks = seq(from = 0, to = 100, by = 10)) +
  scale_y_continuous(breaks = seq(from = 0, to = 60, by = 10))

(Ejercicio A)

  1. A continuación crearemos la pequeña base de datos utilizada para hacer el gráfico mostrado antes por Sebastián Piñera. Utilizando dicha base, genera el gráfico correcto en ggplot2. Este es un caso donde no hay necesidad de editar la escala por defecto. Recuerda utilizar etiquetas (labs) que ayuden a leer mejor el gráfico.
df_victimizacion <- tibble(
  anio               = c(2010, 2013, 2016),
  porc_victimizacion = c(30.7, 22.8, 27.3)
)
df_victimizacion
## # A tibble: 3 x 2
##    anio porc_victimizacion
##   <dbl>              <dbl>
## 1  2010               30.7
## 2  2013               22.8
## 3  2016               27.3

Tu código:

(Nueva base de datos)

Ahora trabajaremos con una base de datos con información de carreras universitarias en Estados Unidos. Su fuente es FiveThirtyEight (2018), aunque estos datos específicos fueron editados para Tidy Tuesday.

carreras_eeuu <- read_csv("datos/carreras_eeuu.csv")
## Parsed with column specification:
## cols(
##   carrera_codigo = col_double(),
##   carrera = col_character(),
##   carrera_tipo1 = col_character(),
##   carrera_tipo2 = col_character(),
##   estudiantes_total = col_double(),
##   estudiantes_muj = col_double(),
##   estudiantes_hom = col_double(),
##   salario_mediana = col_double(),
##   salario_q1 = col_double(),
##   salario_q3 = col_double(),
##   en_part_time = col_double(),
##   en_trabajos_calificados = col_double(),
##   en_trabajos_no_calificados = col_double(),
##   en_trabajos_sueldo_min = col_double(),
##   desempleados = col_double()
## )
glimpse(carreras_eeuu)
## Rows: 171
## Columns: 15
## $ carrera_codigo             <dbl> 1100, 1101, 1102, 1103, 1105, 1106, 1199, 1301, 1302, 1303, 1401, 1501, 1901, 1902, 1903, 1904, 2001, 2100, 2101, 2102, 2105, 2106, 2107, 2201, 2300, 2301, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, ...
## $ carrera                    <chr> "Agricultura (General)", "Producción y Manejo Agrícola", "Economía Agrícola", "Ciencias Animales", "Agronomía", "Ciencias del Suelo", "Agricultura (Misceláneo)", "Ciencias Ambientales", "Ciencias Forestales", "...
## $ carrera_tipo1              <chr> "STEM", "STEM", "STEM", "STEM", "STEM", "STEM", "STEM", "STEM", "STEM", "STEM", "STEM", "Humanidades y Ciencias Sociales", "Humanidades y Ciencias Sociales", "Humanidades y Ciencias Sociales", "Humanidades y Ci...
## $ carrera_tipo2              <chr> "Agricultura y Recursos Naturales", "Agricultura y Recursos Naturales", "Agricultura y Recursos Naturales", "Agricultura y Recursos Naturales", "Agricultura y Recursos Naturales", "Agricultura y Recursos Natura...
## $ estudiantes_total          <dbl> 10399, 14240, 2439, 21573, 7416, 685, 1488, 25965, 3607, 13773, 46420, 31195, 213996, 72619, 52824, 53162, 18035, 36698, 4168, 128319, 11913, 8066, 7613, 10510, 143718, 804, 818, 170862, 14237, 28213, 37589, 64...
## $ estudiantes_muj            <dbl> 6053, 9658, 1749, 5347, 4897, 476, 404, 10787, 3156, 8617, 25463, 8739, 70619, 23736, 24704, 12862, 11431, 27392, 3046, 99743, 9005, 6607, 5291, 4364, 26893, 280, 119, 13029, 3872, 15670, 1167, 2049, 6820, 2682...
## $ estudiantes_hom            <dbl> 4346, 4582, 690, 16226, 2519, 209, 1084, 15178, 451, 5156, 20957, 22456, 143377, 48883, 28120, 40300, 6604, 9306, 1122, 28576, 2908, 1459, 2322, 6146, 116825, 524, 699, 157833, 10365, 12543, 36422, 4434, 10305,...
## $ salario_mediana            <dbl> 40000, 40000, 40000, 30000, 32000, 35000, 29000, 35600, 35000, 35000, 40000, 35000, 35000, 35000, 33000, 35000, 35000, 45000, 41300, 53000, 45000, 37500, 36400, 29000, 34000, 34000, 41000, 32000, 34000, 31000, ...
## $ salario_q1                 <dbl> 30000, 25000, 27000, 22000, 22900, 18500, 23000, 25000, 28600, 25000, 31000, 24500, 27000, 26000, 25000, 27000, 25000, 30000, 20000, 39000, 32500, 25000, 27000, 20000, 26000, 29000, 41000, 23400, 30000, 24000, ...
## $ salario_q3                 <dbl> 50000, 50000, 54000, 40000, 40000, 44000, 42100, 40200, 48000, 42000, 50000, 44000, 45000, 42900, 45000, 47000, 45000, 60000, 46000, 70000, 58000, 50000, 49000, 36000, 41000, 35000, 43000, 38000, 40000, 40000, ...
## $ en_part_time               <dbl> 2031, 2196, 620, 5353, 1246, 185, 335, 7071, 891, 2613, 10206, 9541, 49889, 15902, 13078, 10948, 4690, 4332, 482, 18726, 1468, 1030, 1447, 2064, 29558, 0, 135, 37965, 2273, 7230, 7001, 1227, 3782, 5153, 5168, 2...
## $ en_trabajos_calificados    <dbl> 2418, 1925, 535, 5443, 2089, 355, 483, 8149, 1096, 4333, 16178, 8465, 40763, 23279, 12855, 9659, 4545, 13344, 2024, 68622, 4390, 2354, 2593, 563, 82007, 346, 509, 108085, 10699, 12777, 23515, 4214, 10304, 20185...
## $ en_trabajos_no_calificados <dbl> 4717, 6221, 893, 9571, 3545, 144, 626, 10076, 1692, 5808, 13724, 11818, 97964, 26672, 25297, 23059, 8794, 11783, 1033, 25667, 4102, 3244, 2941, 7384, 31112, 206, 221, 36972, 1977, 9328, 7705, 1106, 3967, 3797, ...
## $ en_trabajos_sueldo_min     <dbl> 839, 1362, 94, 2125, 1231, 0, 31, 3175, 327, 1405, 4221, 3677, 27440, 8512, 6429, 7214, 2495, 1672, 263, 5144, 608, 308, 352, 3163, 11443, 111, 0, 11502, 786, 2042, 2868, 591, 1385, 1179, 1806, 722, 2819, 2767,...
## $ desempleados               <dbl> 178, 649, 182, 917, 314, 0, 82, 1779, 322, 842, 4366, 1668, 14602, 4535, 4410, 3305, 2006, 2934, 419, 6884, 639, 721, 1100, 510, 7195, 0, 88, 7297, 216, 1920, 1360, 266, 833, 1067, 1012, 496, 1379, 1206, 547, 2...

(Ejercicio B)

Antes de comenzar a trabajar con los datos, crea una nueva base de datos llamada “carreras_eeuu2” que tenga tres nuevas variables: porc_mujeres, porc_desempleo, porc_en_trabajos_calificados (todas calculadas con respecto al total de cada carrera). Tu código:

En el resto de la clase utilizaremos esta base modificada.

Elegir buenas escalas de colores

Escalas de colores categóricas

Comencemos dibujando solo el plano de coordenadas, sin geoms. ¿Qué esperan ver en el siguiente gráfico, una vez que añadamos geom_point()?

ggplot(data    = carreras_eeuu2,
       mapping = aes(x = porc_desempleo, 
                     y = porc_en_trabajos_calificados, 
                     color = carrera_tipo1))

Veamos el gráfico:

ggplot(data    = carreras_eeuu2,
       mapping = aes(x = porc_desempleo, y = porc_en_trabajos_calificados, color = carrera_tipo1)) +
  geom_point()

La paleta de colores categóricos por defecto de ggplot2, lamentablemente, es difícil de ver para los/as daltónicos/as. Podemos cambiarla por una de ColorBrewer con el comando scale_color_brewer():

ggplot(data    = carreras_eeuu2,
       mapping = aes(x = porc_desempleo, y = porc_en_trabajos_calificados, color = carrera_tipo1)) +
  geom_point() +
  scale_color_brewer(palette = "PuOr")

Escalas de colores numéricas

Grafiquemos la misma relación de antes, pero esta vez añadamos color a los puntos con una variable continua (porc_mujeres):

ggplot(data    = carreras_eeuu2,
       mapping = aes(x = porc_desempleo, y = porc_en_trabajos_calificados,
                     color = porc_mujeres)) +
  geom_point()

De nuevo, la paleta de colores por defecto es subóptima. La mejor paleta para visualizar escalas continuas en color es “viridis”. Podemos utilizarla con el comando scale_color_viridis_c():

ggplot(data    = carreras_eeuu2,
       mapping = aes(x = porc_desempleo, y = porc_en_trabajos_calificados, color = porc_mujeres)) +
  geom_point() +
  scale_color_viridis_c() # de la escala

(Ejercicio C)

Genera un gráfico de dispersión para dos variables numéricas en la base de datos. Añade color a las observaciones de acuerdo al tipo de carrera (amplio). Utiliza una escala de ColorBrewer distinta a la de antes. Recuerda utilizar buenos labs (etiquetas). Tu código:

Texto dentro del gráfico

Para el último gráfico que hicimos, nos puede interesar ver la posición de carreras específicas. Podemos generar esto añadiendo texto dentro del gráfico:

ggplot(data    = carreras_eeuu2,
       mapping = aes(x = porc_desempleo, 
                     y = porc_en_trabajos_calificados, 
                     color = porc_mujeres,
                     label = carrera)) + 
  geom_point() +
  geom_label() + # esto genera los textos, ojo que necesita el mapeo de "label" antes!
  scale_color_viridis_c()

Esto último es inútil, pues no se entiende nada. Podemos destacar solo una carrera si construimos geom_label() usando datos parciales. Coloquemos solo el texto para ciencia política:

ggplot(data    = carreras_eeuu2,
       mapping = aes(x = porc_desempleo, 
                     y = porc_en_trabajos_calificados, 
                     color = porc_mujeres,
                     label = carrera)) +
  geom_point() +
  geom_label(data = carreras_eeuu2 %>% 
               filter(carrera == "Ciencia Política"),
             alpha = 0.7) +
  scale_color_viridis_c()

¿Cómo ponemos múltiples textos con claridad en un gráfico? Aquí nos será muy útil el paquete ggrepel:

#install.packages("ggrepel")
library(ggrepel)
ggplot(data    = carreras_eeuu2,
       mapping = aes(x = porc_desempleo, 
                     y = porc_en_trabajos_calificados, 
                     color = porc_mujeres,
                     label = carrera)) +
  geom_point() +
  # usamos ahora geom_label_repel()
  geom_label_repel(data = carreras_eeuu2 %>% 
                     filter(carrera == "Ciencia Política"),
                   alpha = 0.7,
                   # lo siguiente obliga a ggrepel a dibujar las líneas de guía:
                   min.segment.length = 0) +
  scale_color_viridis_c()

No parece que haya hecho demasiado. ggrepel es particularmente útil para visualizar varios textos dentro de un gráfico. Por ejemplo, ahora veamos todas las carreras de comunicaciones:

ggplot(data    = carreras_eeuu2,
       mapping = aes(x = porc_desempleo, 
                     y = porc_en_trabajos_calificados, 
                     color = porc_mujeres,
                     label = carrera)) +
  geom_point() +
  geom_label_repel(data = carreras_eeuu2 %>% 
                     filter(carrera_tipo2 == "Comunicaciones"),
                   min.segment.length = 0, alpha = 0.7,
                   size = 4) +
  scale_color_viridis_c()

Texto dentro de gráficos de columna

Calculemos la mediana de porcentaje de desempleo por tipo (amplio) de carrera:

ggplot(data    = carreras_eeuu2 %>% 
         group_by(carrera_tipo1) %>% 
         summarize(median_porc_desempleo = median(porc_desempleo)),
       mapping = aes(x = carrera_tipo1, y = median_porc_desempleo)) +
  geom_col()
## `summarise()` ungrouping output (override with `.groups` argument)

Para añadir cajas de texto con los valores numéricos al gráfico, de nuevo podemos utilizar geom_label(), luego de haber indicado el mapeo estético para “label”:

ggplot(data    = carreras_eeuu2 %>% 
         group_by(carrera_tipo1) %>% 
         summarize(median_porc_desempleo = median(porc_desempleo)),
       mapping = aes(x = carrera_tipo1, y = median_porc_desempleo, 
                     label = median_porc_desempleo)) +
  geom_col() +
  geom_label()
## `summarise()` ungrouping output (override with `.groups` argument)

Un tip: podemos redondear los números utilizando round() en el mapeo de label:

ggplot(data    = carreras_eeuu2 %>% 
         group_by(carrera_tipo1) %>% 
         summarize(median_porc_desempleo = median(porc_desempleo)),
       mapping = aes(x = carrera_tipo1, y = median_porc_desempleo, 
                     label = round(median_porc_desempleo, 2))) +
  geom_col() +
  geom_label()
## `summarise()` ungrouping output (override with `.groups` argument)

Por cierto, aparte de geom_label() está geom_text(), que no dibuja una caja alrededor del texto.

ggplot(data    = carreras_eeuu2 %>% 
         group_by(carrera_tipo1) %>% 
         summarize(mediana_porc_desempleo = median(porc_desempleo)),
       mapping = aes(x = carrera_tipo1, y = mediana_porc_desempleo, 
                     label = round(mediana_porc_desempleo, 2))) +
  geom_col() +
  geom_text(vjust = -0.4) # solo esto cambió. vjust cambia ligeramente la posición del texto
## `summarise()` ungrouping output (override with `.groups` argument)

(Ejercicio D)

Genera un gráfico de tipo “ránking” con la diez carreras con mayor salario mediano. Registra con texto los valores de salarios medianos. ¡Utiliza buenos labs (etiquetas)!