Gráficas con ggplot2
Parte 2: Graficación avanzada en R
ggplot2
: cómo formatear el texto con otros colores usando gridtext
, cómo agregar en la misma gráfica datos de dos fuentes distintas, cómo juntar gráficas usando cowplot
y cómo agregar logotipos a gráficas.
1 Unión de gráficos con cowplot
Muchas veces interesa tener una gráfica que conjunte dos imágenes distintas. Por ejemplo la siguiente imagen muestra dos histogramas lado a lado en una sola gráfica.
Para poder juntarlos es necesario: 1) hacer cada histograma por separado y 2) usar el paquete cowplot
para juntarlos.
Empecemos elaborando el primer histograma a partir de los datos de diabetes
:
<- read_csv("datasets/diabetes.csv")
datos_diabetes
<- ggplot(datos_diabetes) +
histograma_1 geom_histogram(aes(x = chol, y = ..density..),
bins = 50, color = "white", fill = "deepskyblue3") +
labs(
y = "",
x = "Niveles de colesterol"
+
) scale_y_continuous(labels = scales::percent) +
theme_classic()
continuemos con el segundo:
<- ggplot(datos_diabetes) +
histograma_2 geom_histogram(aes(x = stab.glu, y = ..density..),
bins = 50, color = "white", fill = "deepskyblue3") +
labs(
y = "",
x = "Niveles de glucosa"
+
) scale_y_continuous(labels = scales::percent) +
theme_classic()
Finalmente con plot_grid
dentro de cowplot
las juntamos:
library(cowplot) #para usar plot_grid
plot_grid(histograma_1, histograma_2, ncol = 2) #ncol indica cuántas columnas
El paquete cowplot
permite incluso combinar más de dos gráficos y establecer las alturas.
1.1 Ejercicios
- Para armar el siguiente gráfico se utilizaron
histograma_1
,histograma_2
y una tercera gráfica decolesterol
contraglucosa
de esta forma (colordeepskyblue4
):
La gráfica de colesterol contra glucosa se almacenó en la variable col_glu
la cual luego se utilizó en el plot_grid
con la siguiente instrucción:
plot_grid(histograma_1, #Primer histograma
ggplot() + theme_void(), #Genera un gráfico vacío
#Gráfica de glucosa vs colesterol
col_glu, + coord_flip(), #coord_flip voltea el histograma
histograma_2 ncol = 2, #dos columnas
rel_widths = c(1, 0.5), #Establece el ancho relativo
rel_heights = c(0.5, 1)) #Establece la altura relativa
Reproduce la gráfica
2 Formateo de títulos con ggtext
La librería ggtext
sirve para poner negritas, cursivas y cambiar colores en los textos. Probemos con la base de datos datasets/BCG_Sin_Son_2020_IMSS.csv
que contiene información de las dosis de BCG
en Sinaloa y Sonora aplicadas en el IMSS.
#Lectura de datos
<- read_csv("datasets/BCG_Sin_Son_2020_IMSS.csv")
bcg_ss
#Gráfico de tendencias
ggplot(bcg_ss) +
geom_line(aes(x = Año, y = Dosis, color = Entidad)) +
scale_color_manual("Entidad", values = c("Sinaloa" = "deepskyblue4",
"Sonora" = "deeppink3")) +
theme_minimal() +
labs(
x = "Año",
y = "Dosis de B.C.G. (Bacillus Calmette–Guérin)",
title = "Dosis de B.C.G aplicadas en el IMSS en Sonora y Sinaloa",
caption = "Fuente: Datos abiertos del IMSS"
)
A través de ggtext
podemos colorear sólo secciones del título poniéndolas entre las etiquetas <span style = 'color:nombredelcolor;'>
y </span>
. Podemos poner negritas usando dos asteriscos como en whatsapp, **
lo que va en negritas**
, y cursivas con guiones bajos, _
lo que va en cursivas_
. Para poner espacios verticales basta con escribir un <br>
y eso de inmediato da un espacio. Finalmente para que los temas apliquen hay que cambiar a element_markdown
las opciones donde queremos aplicar el tema dentro del theme
(nuestro caso plot.title
, axis.title.y
y plot.capiton
pero también se puede en axis.title.x
y plot.subtitle
).
library(ggtext)
#Gráfico de tendencias
ggplot(bcg_ss) +
geom_line(aes(x = Año, y = Dosis, color = Entidad)) +
scale_color_manual("Entidad", values = c("Sinaloa" = "deepskyblue4",
"Sonora" = "deeppink3")) +
theme_minimal() +
labs(
x = "Año",
y = "Dosis de B.C.G. (_Bacillus Calmette-Guérin_)",
title =
"**Dosis de B.C.G aplicadas en el IMSS en
<span style = 'color:deeppink3;'>Sonora</span> y
<span style = 'color:deepskyblue4;'>Sinaloa</span>.**",
caption = "**Fuente:** Datos abiertos del IMSS"
+
) theme(
plot.title = element_markdown(),
axis.title.y = element_markdown(),
plot.caption = element_markdown()
)
dentro de los element_markdown
se pueden cambiar los tamaños de fuentes como lo hicimos en la sección pasada con element_text
: son lo mismo. También podemos esconder la leyenda con legend.position = "none"
dentro del theme
:
library(ggtext)
#Gráfico de tendencias
ggplot(bcg_ss) +
geom_line(aes(x = Año, y = Dosis, color = Entidad)) +
scale_color_manual("Entidad", values = c("Sinaloa" = "deepskyblue4",
"Sonora" = "deeppink3")) +
theme_minimal() +
labs(
x = "Año",
y = "Dosis de B.C.G.<br>(_Bacillus Calmette-Guérin_)",
title =
"Dosis de B.C.G aplicadas en
<span style = 'color:deeppink3;'>**Sonora**</span> y
<span style = 'color:deepskyblue4;'>**Sinaloa**</span><br>",
caption = "**Fuente:** Datos abiertos del IMSS"
+
) theme(
plot.title = element_markdown(size = 18),
axis.title.y = element_markdown(),
plot.caption = element_markdown(),
legend.position = "none"
)
2.1 Ejercicio
La base de datos datasets/hpv_unicef.csv
contiene información del objetivo target
de vacunación (primera dosis en mujeres) para el papiloma humano y las dosis que en realidad implementaron doses
en 2021 para los países que se tiene registro.
<- read_csv("datasets/hpv_unicef.csv") hpv
Podemos notar en la base que México tenía un objetivo de 1094757
y aplicó 13512
. La siguiente gráfica subraya a México dentro de los datos:
ggplot(hpv) +
geom_point(aes(x = target, y = doses), color = "gray25",
size = 1) +
geom_point(aes(x = 1094757, y = 13512), color = "tomato3",
size = 2, data = NULL) +
scale_x_continuous(labels = scales::comma) +
scale_y_continuous(labels = scales::comma) +
theme_minimal() +
labs(
x = "Dosis objetivo",
y = "Dosis aplicadas",
)
Modifica la gráfica para que el resultado sea el siguiente:
3 Uso de múltiples bases de datos en la misma gráfica
La base de datos datasets/hpv_unicef_ultima_dosis.csv
contiene la información de cobertura doses
y cobertura objetivo target
de la última dosis de la vacuna de VPH en mujeres. La base datasets/hpv_unicef.csv
contiene la misma información pero para la primera dosis. Hagamos una nube de puntos con ambas bases en conjunto. Para ello podemos usar ggplot
pero ahora especificaremos dentro del geom_point
el parámetro data
<- read_csv("datasets/hpv_unicef.csv")
primera_dosis <- read_csv("datasets/hpv_unicef_ultima_dosis.csv") ultima_dosis
Realizamos la gráfica nota que hay que poner dos geom_point
s uno para cada fuente de datos data
:
#Aquí puedes poner la base que quieras o dejar vacío
ggplot() +
geom_point(aes(x = target, y = doses), data = primera_dosis) +
geom_point(aes(x = target, y = doses), data = ultima_dosis) +
scale_x_continuous(labels = scales::comma) +
scale_y_continuous(labels = scales::comma)
Podemos agregar una leyenda para que R
distinga las primeras de las últimas. Si bien eso no depende de la base de datos podemos meterlo dentro del aes
junto con el nombre a asignar:
#Aquí puedes poner la base que quieras o dejar vacío
ggplot() +
geom_point(aes(x = target, y = doses, color = "Primera"),
data = primera_dosis, alpha = 0.5) +
geom_point(aes(x = target, y = doses, color = "Última"),
data = ultima_dosis, alpha = 0.5) +
scale_x_continuous(labels = scales::comma) +
scale_y_continuous(labels = scales::comma)
Para visualizar mehor la información cambiaré la escala a escala logarítmica:
#Aquí puedes poner la base que quieras o dejar vacío
ggplot() +
geom_point(aes(x = target, y = doses, color = "Primera"),
data = primera_dosis, alpha = 0.5) +
geom_point(aes(x = target, y = doses, color = "Última"),
data = ultima_dosis, alpha = 0.5) +
scale_x_log10(labels = scales::comma) +
scale_y_log10(labels = scales::comma)
Finalmente terminamos la personalización para tener la gráfica final:
#Aquí puedes poner la base que quieras o dejar vacío
ggplot() +
geom_point(aes(x = target, y = doses, color = "Primera"),
data = primera_dosis, alpha = 0.5, size = 2) +
geom_point(aes(x = target, y = doses, color = "Última"),
data = ultima_dosis, alpha = 0.5, size = 2) +
scale_x_log10(labels = scales::comma) +
scale_y_log10(labels = scales::comma) +
labs(
x = "Dosis objetivo",
y = "Dosis aplicadas",
title = "Dosis objetivo y aplicadas para la vacuna contra el VPH",
subtitle = "Primera y última dosis aplicadas en mujeres",
caption = "Fuente: Datos de inmunización de UNICEF"
+
) scale_color_manual("Dosis", values = c("Primera" = "#FAA916",
"Última" = "#96031A")) +
theme_linedraw()
3.1 Ejercicio
Las bases de datos unicef_dtp_1.csv
y unicef_dtp_3.csv
contienen la covertura de inmunización (DTP1 y DTP3 respectivamente) por país y año. Reproduce la siguiente gráfica donde la leyenda se pasó abajo mediante el comando legend.position = "bottom"
dentro de theme
. Los colores son: "DPT-1" = "#214F4B"
y "DPT-3" = "#16C172"
.
4 Agregar logotipos
Los logotipos usualmente vienen en dos formatos distintos. Muchas veces vienen como svg
. Las svg
son los formatos preferidos pues son imágenes que no se pixelean aunque les hagas zoom. En ocasiones el svg
no está disponible en cuyo caso el logo puede venir en cualquier formato de imagen png
, jpeg
, etc. Las instrucciones para trabajar con uno o con otro son muy similares y haremos ambos casos usando los logos del IMSS IMSS_Logo.png
y Logotipo_del_IMSS.svg
en la carpeta images
.
En ambos casos usaremos las librerías magick
y ggimage
:
library(magick) #Leer la imagen
library(cowplot) #Poner la imagen en ggplot2
En el caso de la imagen en svg
podemos leerla como:
<- image_read_svg("imagenes/Logotipo_del_IMSS.svg", width = 1000) img
donde el parámetro width
controla qué tan bien se ve la imagen: a mayor width
menor pixeleo del logo (pero también más tiempo de procesamiento).
Ojo la imagen no se va a ver aún pero ya la tenemos almacenada en img
.
Para agregar el logo necesitamos una gráfica en la cual nos interese poner el logotipo. Yo trabajaré con el histograma que hicimos antes que utiliza la base de datos de diabetes:
#Si ya tenías los datos no es necesario volver a leerlos
<- read_csv("datasets/diabetes.csv")
datos_diabetes
#Grafico el histograma. No le estoy poniendo formato porque
#en lo que quiero enfocarme es en el logotipo
ggplot(datos_diabetes) +
geom_histogram(aes(x = chol))
Para poner la imagen es suficiente con usar draw_image
y especificar las coordenadas x
y y
donde queremos que vaya. El parámetro scale
controla qué tan grande o pequeña la queremos:
ggplot(datos_diabetes) +
geom_histogram(aes(x = chol)) +
draw_image(img, x = 400, y= 40, scale=50)
exactamente el mismo proceso puede replicarse si el logo viene en png
:
#Aquí no se pone width pues el png ya tiene un width predefinido
<- image_read("imagenes/IMSS_Logo.png")
img_png
#Realizamos la gráfica
ggplot(datos_diabetes) +
geom_histogram(aes(x = chol)) +
draw_image(img_png, x = 400, y= 40, scale=50)
4.1 Ejercicio
- Agrega el logo del Instituto Nacional de Salud Pública (link de descarga) a la siguiente gráfica en el centro del corazón:
#Armamos la base de datos
= tibble(
heartdf t = seq(0, 2*pi, pi/60),
x = 16*sin(t)^3,
y = 13*cos(t) - 5*cos(2*t) - 2*cos(3*t) - cos(4*t)
)
#Generamos la gráfica
ggplot(data = heartdf, aes(x, y)) +
geom_polygon(aes(group = 1), color = "#DDCCAA",
fill = "white", size = 2) +
theme_classic() +
coord_fixed() +
labs(
x = "",
y = ""
+
) theme(axis.ticks = element_blank())
5 Cambio de fuente
La librería showtext
es bastante útil para cambiar el tipo de fuente en los textos de un ggplot
. Para ello es necesario llamar a la librería:
library(showtext)
Para agregar una fuente elige el nombre de la fuente de Google. La lista completa de fuentes puedes hallarla en https://fonts.google.com/:
font_add_google("Schoolbell", "Schoolbell")
para que R
sepa que hay que usar showtext
agrega esta línea:
showtext_auto()
Finalmente en tu gráfica agrega dentro del element_text
de theme
la fuente con su nombre. Por ejemplo a la siguiente base de datos:
#Genera una base de datos inventada
set.seed(34659)
<- data.frame(x = rnorm(100))
datos
#Grafica
ggplot(datos) +
geom_histogram(aes(x = x)) +
labs(
title = "Histograma"
)
le podemos cambiar el texto sólo del título:
#Grafica
ggplot(datos) +
geom_histogram(aes(x = x), bins = 10, color = "white") +
labs(
title = "Histograma"
+
) theme(
plot.title = element_text(family = "Schoolbell", size = 20)
)
Los cambios pueden hacerse de manera idéntica con plot.subtitle
, plot.caption
, axis.text
y axis.title
.
5.1 Ejercicio
- Descarga la fuente
Peralta
y replica la siguiente gráfica usando losdatos
generados anteriormente.
#Genera una base de datos inventada
set.seed(34659)
<- data.frame(x = rnorm(100))
datos
font_add_google("Peralta","Peralta")
ggplot(datos) +
geom_histogram(aes(x = x), bins = 10, color = "white") +
theme_classic() +
labs(
title = "Título",
y = "Eje y",
x = "Eje x",
caption = "Pie de figura",
subtitle = "Subtítulo"
+
) theme(
plot.title = element_text(family = "Peralta", size = 20),
plot.subtitle = element_text(family = "Peralta", size = 14),
plot.caption = element_text(family = "Peralta", size = 10),
axis.text = element_text(family = "Peralta"),
axis.title = element_text(family = "Peralta"),
)
6 Uso de gghighlight
para resaltar valores
Considera la misma base de datos IMSS_BCG_2020.csv
que utilizamos la vez pasada donde graficamos las Dosis BCG
aplicadas en el IMSS.
<- read_csv("datasets/IMSS_BCG_2020.csv")
bcg
ggplot(bcg) +
geom_col(aes(x = Del, y = `Dosis BCG`),
fill = "deepskyblue4") +
theme_minimal() +
labs(
x = "Delegación",
y = "Dosis aplicadas",
subtitle = "Año 2020",
title = "Dosis B.C.G. aplicadas en el IMSS"
+
) theme(axis.text.x = element_text(angle = 90,
hjust = 1, vjust = 0.5))
Supongamos que nos interesa resaltar aquellas delegaciones con más de 20000
dosis aplicadas. El paquete de gghighlight
ayuda con esto. Basta con poner gghighlight
después del geom
para hacerlo:
library(gghighlight)
ggplot(bcg) +
geom_col(aes(x = Del, y = `Dosis BCG`),
fill = "deepskyblue4") +
gghighlight(`Dosis BCG` > 20000) +
theme_minimal() +
labs(
x = "Delegación",
y = "Dosis aplicadas",
subtitle = "Año 2020",
title = "Dosis B.C.G. aplicadas en el IMSS"
+
) theme(axis.text.x = element_text(angle = 90,
hjust = 1, vjust = 0.5))
Hay distintas opciones dentro de gghighlight
en particular para cambiar el color y la transparencia de los no subrayados:
#alpha es la transparencia (entre 0 y 1)
#fill es el relleno puede ser NULL si no deseas que cambie el color
ggplot(bcg) +
geom_col(aes(x = Del, y = `Dosis BCG`),
fill = "tomato3") +
gghighlight(`Dosis BCG` > 20000,
unhighlighted_params = list(fill = "deepskyblue4", alpha = 1)) +
theme_minimal() +
labs(
x = "Delegación",
y = "Dosis aplicadas",
subtitle = "Año 2020",
title = "Dosis B.C.G. aplicadas en el IMSS"
+
) theme(axis.text.x = element_text(angle = 90,
hjust = 1, vjust = 0.5))
6.1 Ejercicio
En la siguiente gráfica a partir de los datos de diabetes
colorea aquellos puntos donde el índice de masa corporal dado por (weight * 0.453592) /(height * 0.0254)^2
sea mayor a 25 (exceso de peso) para obtener una gráfica similar a la siguiente con tus colores favoritos.
Recuerda que para pasar el peso
weight
de libras a kilogramos hay que multiplicarlo por0.453592
y para pasar la alturaheight
a metros es necesario multiplicarla por0.0254
.
7 Ejercicios de cierre de la sección
El archivo datasets/vacuna_unicef_regional.csv
contiene la información de la cobertura de las inmunizaciones a nivel región desde 1980 por tipo de vacuna. Utiliza todo lo que sabes para reproducir la siguiente gráfica que utiliza la fuente Manrope
. Los colores utilizados son:
"LACR" = "#2c525c",
"EAPR" = "#0a6569",
"ECAR" = "#00786a",
"ESAR" = "#1b8a5e",
"MENA" = "#509947",
"ROSA" = "#84a428",
"WCAR" = "#bfa900",
"Non-programme" = "#ffa600",
"Global" = "black"
el color de fondo de la gráfica es #fffff8
, el tema es classic
y el relleno de los strip.background
es #2c525c
.
Nota La región de México es
LACR
(Latinoamérica y el Caribe).