🏠↩︎ De vuelta a la página principal del curso


Inicio

🚀 Objetivo de la unidad

Que el estudiante conozca los distintos tipos de visualización de datos y reconozca sus casos de uso.


🇷 ⬇ Descargar projecto de R de la práctica 🇷 ⬇ Descargar projecto de R de la práctica (Pirámide poblacional)


4.1. Instalando y cargando paquetes

# install.packages("ggplot2")
# install.packages("svglite") # Para expotar como svg
library(data.table)
library(ggplot2)


4.2. Cargando conjuntos de datos

Para la práctica utilizaremos los siguientes conjuntos de datos:

mw <- data.table(ggplot2::midwest)


* El archivo Personas09.csv contiene los microdatos a nivel persona de la Ciudad de México del Censo de Población y Vivienda 2020 del INEGI en formato csv. Este archivo está disponible para su descarga aquí (Archivos para descarga > Muestra (cuestionario ampliado) > Bases de datos > Ciudad de México > CSV ⬇).

p_raw <- fread("../data/Censo2020_CA_cdmx_csv/Personas09.CSV")


4.3. Los básicos

Para crear una visualización, debemos:

  1. Llamar a la función ggplot(), que crea un lienzo en blanco.
  2. Especificar con aes() cómo deseamos asignar variables a atributos estéticos.
  3. Agregar capas de objetos geométricos con geom_...().
  4. Añadir capas adicionales de facetas, transformaciones estadísticas, coordenadas, temas, entre otros, conforme lo requiera el objetivo de nuestra visualización de datos.

Cada capa de la visualización se apila con el opeerador +.

Creamos lienzo en blanco

ggplot()

💡 Recuerde que nuestras visualizaciones se iran desplegando en la ventana de Plots o, en el caso de visualizaciones interactivas, en la ventana de Viewer.


4.4. Datos

La primera y más importante capa en la gramática de gráficos son los datos. El objeto que contiene los datos con los que construiremos nuestra visualización se pasa como parámetro de la función ggplot().

ggplot(data = mw)


4.5. Estética

El siguiente paso es definir la variable que deseamos usar para cada atributo estético de la visualización.

En la capa de la estética utilizamos la función aes() para asignar variables de datos a atributos gráficos utilizados por el sistema de dibujo subyacente, como posición 2D, color, tipo de línea, tamaño, figura de los puntos, entre otros.

ggplot(data = mw) +
  aes(x = percollege, y = percbelowpoverty, color = state)


4.6. Objetos geométricos

Después de definir los atributos gráficos que deseamos utilizar, debemos especificar uno o varios objetos geométricos para indicar cómo deben dibujarse los puntos de datos. Los objetos geométricos (o geoms) pueden ser puntos, líneas, barras, polígonos, áreas, histogramas, rectas con el mejor ajuste, entre otros. Cuál utilizar dependerá del tipo y total de variables de datos que querramos representar y qué mensaje querramos comunicar con la visualización.

💡 El sitio The R Graph Gallery contiene decenas de ejemplos con código en R de visualizaciones de datos. “Imitation is not just the sincerest form of flattery - it’s the sincerest form of learning.

ggplot(data = mw) +
  aes(x = percollege, y = percbelowpoverty) + 
  geom_point()


Los objetos geométricos tienen sus propios parámetros para ajustar sus atributos gráficos.

ggplot(data = mw) +
  aes(x = percollege, y = percbelowpoverty) + 
  geom_point(color = "purple", alpha = 0.50, size = 3)


Es posible agrupar cuantos objetos geométricos querramos.

ggplot(data = mw) +
  aes(x = percollege, y = percbelowpoverty) + 
  geom_point() +
  geom_smooth()
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'


Algunos geoms utilizan transformaciones estadísticas que aplican cálculos y agregaciones de forma implícita a los datos antes de graficarlos.

mw[, above_5_percblack := ifelse(test = percblack >= 5, yes = "Sí", no = "No")]
ggplot(data = mw) +
  aes(x = state, fill = above_5_percblack) + 
  geom_bar(stat = "count")


ggplot(data = mw) +
  aes(x = poptotal) + 
  geom_histogram(bins = 100)


ggplot(data = mw) +
  aes(x = percpovertyknown, y = state) + 
  geom_boxplot()

💡 Sobre las visualizaciones de caja en ggplot2:

  • Cada línea vertical representa el cuartil 25, el 50 (la mediana) y el 75 respectivamente.
  • La caja representa el rango intercuartílico (diferencia entre los percentiles 75 y 25).
  • El límite izquiero del bigote izquierdo representa el valor mínimo de los datos que está dentro de 1.5 veces el rango intercuartílico por debajo del percentil 25.
  • El límite derecho del bigote derecho representa el valor máximo de los datos que está dentro de 1.5 veces el rango intercuartílico sobre el percentil 75.
  • Los puntos representan los valores atípicos, que se consideran cualquier valor inferior a 1.5 veces el rango intercuartílico sobre el percentil 75 o cualquier valor izquierdo a 1.5 veces el rango intercuartílico bajo el percentil 25.


Igualmente, es posible especificar objetos primitivos, es decir, objetos geométricos independientes de los datos.

mu <- mean(mw[, percpovertyknown])
ggplot(data = mw) +
  aes(x = percpovertyknown, y = state) + 
  geom_boxplot() +
  geom_vline(xintercept = mu, linetype = "dotted")


4.7. Escalas

Cada vez que asignamos variables de datos a atributos gráficos (con la función aes()), ggplot2 usa una escala particular para determinar el rango de valores al que se deben asignar los datos.

Por ejemplo, cuando especificamos: ggplot(data = mw) + aes(x = percollege, y = percbelowpoverty) + geom_point(), ggplot2 agrega automáticamente una escala predeterminada para cada asignación.

Cada escala se puede representar mediante una función con el siguiente nombre: scale_, seguido del nombre del atributo estética, seguido de un _ y seguido el tipo de dato de la variable de la escala.

ggplot(data = mw) + 
  aes(x = percollege, y = percbelowpoverty) + 
  geom_point() +
  scale_x_continuous() +
  scale_y_continuous() + 
  scale_colour_discrete()


Si bien las escalas predeterminadas funcionan bien, es posible agregar explícitamente diferentes escalas para reemplazar las predeterminadas.

ggplot(data = mw) + 
  aes(x = percollege, y = percbelowpoverty) + 
  geom_point() +
  scale_x_reverse() +
  scale_y_reverse()


ggplot(data = mw) + 
  aes(x = percollege, y = percbelowpoverty, color = state) + 
  geom_point() +
  scale_color_manual(values = c("#993300", "#ff3300", "#ff6600", "#ff9999", "#ffccff")) # Colores definidos con su código hexadecimal


ggplot(data = mw) + 
  aes(x = percollege, y = percbelowpoverty, color = state) + 
  geom_point() +
  scale_color_brewer(palette = "Blues") # https://rdrr.io/cran/RColorBrewer/man/ColorBrewer.html


4.8. Facetas

Las facetas (o facets) nos permiten agrupar datos por variables y luego graficar cada grupo individualmente un panel independiente, pero en la misma visualización (imagen).


ggplot(data = mw) + 
  aes(x = percollege, y = percbelowpoverty) + 
  geom_point() +
  facet_grid(facets = "state~above_5_percblack")


4.9. Coordenadas

El sistema de coordenadas define cómo se asignan los puntos de datos a ubicaciones gráficos 2D en el plano. Elegir el sistema de coordenadas correcto puede mejorar considerablemente la legibilidad de las visualizaciones de datos.

Al igual que con las escalas, los sistemas de coordenadas se especifican con funciones que comienzan con coord_ y se agregan como una capa.

Existe una serie de diferentes sistemas de coordenadas, que incluye:

  • coord_cartesian() es el sistema de coordenadas cartesianas predeterminado, donde especifica los valores x y y. Este sistema de coordenadas es el predeterminado, por lo que no es necesario agregarlo en cada ocasión como capa. No obstante, especificar sus parámetros permite establecer límites en los ejes, y por tanto, acercar o alejar la visualización.
  • coord_flip() es un sistema de coordenadas cartesianas con el eje x y el eje y “volteados”.
  • coord_polar() es un sistema de coordenadas polares.


ggplot(data = mw) +
  aes(x = state, fill = above_5_percblack) + 
  geom_bar(stat = "count") +
  coord_flip()



4.10. Temas

Otra excelente manera de mejorar la presentación de sus visualizaciones de datos es elegir un tema no predeterminado para que los elementos gráficos destaquen, haciéndolos más bonitos, vibrantes y congruentes con el tipo variables de datos que querramos representar y qué mensaje querramos comunicar con la visualización. ggplot2 incluye varios temas entre los que podemos elegir.

ggplot(data = mw) +
  aes(x = state, fill = above_5_percblack) + 
  geom_bar(stat = "count") +
  coord_flip() + 
  theme_classic()


4.11. Títulos, etiquetas y anotaciones

Los títulos, etiquetas y anotaciones textuales (en el lienzo, los ejes, los objetos geométricos y la leyenda) son una parte importante para hacer que una visualización sea comprensible y que comunique información de manera eficiente. Aunque no es una parte explícita de la gramática de gráficos, se consideraría una variante de objeto geométrico.

ggplot(data = mw) +
  aes(y = state, fill = above_5_percblack) + 
  geom_bar(stat = "count") +
  theme_classic() +
  labs(x = "Total de condados",
       y = "Estado", 
       title = "Illinois es el estado del medio oeste de Estados Unidos de América\ncon mayor número de condados y condados en los que 5% de su población\nes afrodescendiente",
       subtitle = "Total de condados el medio oeste de Estados Unidos de América por estado",
       fill = "Condados en los que\n5% de su población es\nafrodescendiente",
       caption = "Fuente de datos: Censo de Estados Unidos de América del 2000")


4.12. Exportación

Una vez que la visualización esté completa, este se puede exportar desde la ventana de Plots de forma manual o con la función ggsave() de forma programática después de asignar la visualización a un objeto.

v <- ggplot(data = mw) +
  aes(y = state, fill = above_5_percblack) + 
  geom_bar(stat = "count") +
  theme_classic() +
  labs(x = "Total de condados",
       y = "Estado",  
       title = "Illinois es el estado del medio oeste de Estados Unidos de América\ncon mayor número de condados y condados en los que 5% de su población\nes afrodescendiente",
       subtitle = "Total de condados el medio oeste de Estados Unidos de América por estado",
       fill = "Condados en los que\n5% de su población es\nafrodescendiente",
       caption = "Fuente de datos: Censo de Estados Unidos de América del 2000")
ggsave("./viz/myviz.svg", v, width = 10, height = 5)


A pesar de que ggplot2 es una herramienta de visualización de datos robusta, no se tiene un control absoluto de todos los elementos gráficos. Por ello, es recomendable importar la visualización como svg, un formato de archivo vectorial, que después es posible cargar en programas de edición de imágenes digitales alternas para terminar de ajustar los mínimos detalles.

💡 Gimp e Inkscape son programas de edición de imágenes digitales gratuitos en los que resulta muy cómodo el ajuste de visualizaciones de datos.


4.13. Creando una pirámide poblacional

En esta sección de la práctica, construiremos una pirámide poblacional de la Ciudad de México en el 2020.

Creamos nueva variable categórica de tipo factor utilizando la variable “SEXO”.

p_raw[, sexo_cat := factor(SEXO, levels = c(1, 3),  labels = c("Hombres", "Mujeres"))]


Filtramos fuera las observaciones en las que la variable “EDAD” contenga el valor “999” o un NA y seleccionamos únicamente las variables necesarias para nuestra visualización: “ID_PERSONA”, “FACTOR”, “sexo_cat” y “EDAD”.

p <- p_raw[EDAD != 999 & !is.na(EDAD), .(ID_PERSONA, FACTOR, sexo_cat, EDAD)] 


Graficamos la distribución de edad en la población de la Ciudad de México por sexo.

ggplot(data = p) +
  aes(x = EDAD, weight = FACTOR, fill = sexo_cat) + 
  geom_histogram(binwipersonash = 100, position = "identity", alpha = 0.5)
## Warning: Ignoring unknown parameters: binwipersonash
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.


Utilizamos coord_flip() para “voltear” el eje x y el eje y del sistema de coordenadas cartesianas de la visualización.

ggplot(data = p) +
  aes(x = EDAD, weight = FACTOR, fill = sexo_cat) + 
  geom_histogram(binwipersonash = 100, position = "identity", alpha = 0.5) +
  coord_flip()
## Warning: Ignoring unknown parameters: binwipersonash
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.


Creamos nueva variable categórica de tipo factor con grupos quinquenales de edad utilizando la variable “EDAD” con ayuda de la función cut(). De forma predeterminada, las etiquetas de los factores resultantes se construyen utilizando la notación de intervalo (a,b], en donde a no es un valor incluído en el intervalo y b es un valor incluído en el intervalo.

edades_quinquenales <- cut(x = p$EDAD, 
                          breaks = seq(0, 110, by = 5), 
                          include.lowest = TRUE,
                          right = TRUE)
# unique(edades_quinquenales)

p[, edad_quinquenal := edades_quinquenales]


Creamos un nuevo data table con la población total por sexo y grupo quinquenal de edad.

p_grouped <- p[, .(pob = sum(FACTOR)), by = .(sexo_cat, edad_quinquenal)]


Graficamos nevamente la distribución de edad en la población de la Ciudad de México por sexo pero utilizando el nuevo data table agrupado.

ggplot(data = p_grouped) +
  aes(x = edad_quinquenal, y = pob, fill = sexo_cat) + 
  geom_bar(stat = "Identity", position = "identity", alpha = 0.5) +
  coord_flip()


Para que la población de hombres y la población de mujeres se visualicen “reflejadas”, debemos transformar la variable “pob” a negativa para uno de los dos sexos.

p_grouped[, pob := ifelse(sexo_cat == "Hombres", yes = -pob, no = pob)]
ggplot(data = p_grouped) +
  aes(x = edad_quinquenal, y = pob, fill = sexo_cat) + 
  geom_bar(stat = "Identity") +
  coord_flip()


En la última visualización, podemos observar que las etiquetas del eje x, es decir, el total de la población, está en notación científica. R decide utilizar esta notación dada la longitud de las etiquetas. No obstante, la notación científica no es un formato que facilite la lectura. Para ello, personalizaremos los límites, los saltos y las etiquetas de la escala del eje y con scale_y_continuous().

ggplot(data = p_grouped) +
  aes(x = edad_quinquenal, y = pob, fill = sexo_cat) + 
  geom_bar(stat = "Identity") +
  scale_y_continuous(limits = c(-400000, 400000),
                     breaks = seq(-400000, 400000, by = 100000), 
                     labels = c(400, 300, 200, 100, 0, 100, 200, 300, 400))  + 
  coord_flip()


Para ajustar los colores de las barras, utilizamos scale_fill_manual().

ggplot(data = p_grouped) +
  aes(x = edad_quinquenal, y = pob, fill = sexo_cat) + 
  geom_bar(stat = "Identity") +
  scale_fill_manual(values = c("#a35994ff", "#009482ff")) +
  scale_y_continuous(limits = c(-400000, 400000),
                     breaks = seq(-400000, 400000, by = 100000), 
                     labels = c(400, 300, 200, 100, 0, 100, 200, 300, 400))  + 
  coord_flip()


“Limpiamos el desorden” quitando elementos que no agregan valor informativo y bajamos la leyenda abajo para facilitar la asociación de los colores a cada sexo respectivamente.

ggplot(data = p_grouped) +
  aes(x = edad_quinquenal, y = pob, fill = sexo_cat) + 
  geom_bar(stat = "Identity") +
  scale_fill_manual(values = c("#a35994ff", "#009482ff")) +
  scale_y_continuous(limits = c(-400000, 400000),
                     breaks = seq(-400000, 400000, by = 100000), 
                     labels = c(400, 300, 200, 100, 0, 100, 200, 300, 400))  + 
  coord_flip() +
  theme_minimal() + 
  theme(panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank(),
        legend.position = "bottom") 


Agregamos y modificamos los textos adecuados.

ggplot(data = p_grouped) +
  aes(x = edad_quinquenal, y = pob, fill = sexo_cat) + 
  geom_bar(stat = "Identity") +
  scale_fill_manual(values = c("#a35994ff", "#009482ff")) +
  scale_y_continuous(limits = c(-400000, 400000),
                     breaks = seq(-400000, 400000, by = 100000), 
                     labels = c(400, 300, 200, 100, 0, 100, 200, 300, 400)) + 
  coord_flip() +
  labs(title = "Pirámide poblacional de la Ciudad de México", 
       subtitle = "Población total (en miles de personas) por edad quinquenal",
       caption = "Censo de Población y Vivienda 2020 del INEGI\nElaborado por el CEDUA de El Colegio de México") +
  theme_minimal() + 
  theme(panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank(), 
        axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        legend.position = "bottom",
        legend.title = element_blank()) 


Finalmente, podemos crear una nueva variable que utilicemos como etiquetas en las barras y facilitar la lectura del total de la población por grupo quinquenal.

p_grouped[, pob_label := ifelse(sexo_cat == "Hombres", 
                                yes = paste0(round(-pob/1000), "          "), 
                                no = paste0("          ", round(pob/1000)))]
ggplot(data = p_grouped) +
  aes(x = edad_quinquenal, y = pob, fill = sexo_cat, label = pob_label) + 
  geom_bar(stat = "Identity") +
  scale_fill_manual(values = c("#a35994ff", "#009482ff")) +
  scale_y_continuous(limits = c(-400000, 400000),
                     breaks = seq(-400000, 400000, by = 100000), 
                     labels = c(400, 300, 200, 100, 0, 100, 200, 300, 400)) + 
  geom_text(size = 3) + 
  coord_flip() +
  labs(title = "Pirámide poblacional de la Ciudad de México", 
       subtitle = "Población total (en miles de personas) por edad quinquenal",
       caption = "Censo de Población y Vivienda 2020 del INEGI\nElaborado por el CEDUA de El Colegio de México") +
  theme_minimal() + 
  theme(panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank(), 
        axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        legend.position = "bottom",
        legend.title = element_blank()) 


🏋 Ejercicio

  1. Construya la pirámide poblacional de la Ciudad de México en el 2020 empleando porcentajes en lugar de valores absolutos.
  2. Construya la pirámide poblacional de la población de una “característica de las personas” de su interés utilizando microdatos a nivel persona del Censo de Población y Vivienda 2020 del INEGI en formato csv. Puede utilizar datos a nivel nacional o entidad federativa. Por ejemplo, la pirámide poblacional de Oaxaca en el 2020 de personas que hablan algún dialecto o lengua indígena. Adecué los elementos gráficos al mensaje que quiera transmitir con la visualización.