Una imagen vale más que mil palabras: Visualización de datos con ggplot2

Roger M. López

Gramática de gráficos

  • La “gramática de los gráficos” fue propuesta originalmente por Leland Wilkinson, estadístico americano.
  • Permite construir cualquier gráfico a partir de:
    • Datos: el conjunto de datos que se va a graficar.
    • Aesthetics: mapeo de variables a ejes y otras propiedades visuales.
    • Geometrías: formas visuales que representan los datos (puntos, líneas, barras, etc.).

Recordar

Idea central: los gráficos son una combinación de capas, cada una controlada de forma explícita.

Estructura de un gráfico

La forma general de un gráfico en ggplot2 es:

ggplot(data = <DATA>,
       mapping = aes(x = <X>, y = <Y>)) +
  geom_<GEOMETRÍA>()

donde:

  • <DATA>: es el conjunto de datos que se va a graficar.
  • <X> y <Y>: son las variables que se van a graficar en los ejes X e Y, respectivamente.
  • <GEOMETRÍA>: es el tipo de gráfico que se va a crear (puntos, líneas, barras, etc.).


Nota

Aunque en esta clase vamos a ver los gráficos más comunes, ggplot2 permite crear una amplia variedad y personalizarlos de muchas maneras. Para mayor detalle revisar el libro de ggplot2

Primeros pasos: aesthetics

Para utilizar ggplot2, primero debemos instalar y cargar el paquete. En nuestro caso, al instalar tidyverse ya lo tenemos instalado. Por tanto, solo necesitamos cargarlo:

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.2     ✔ tibble    3.2.1
✔ lubridate 1.9.4     ✔ tidyr     1.3.1
✔ purrr     1.0.4     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors

Adicionalmente, vamos a utilizar los datos obtenidos del Fondo Monetario Internacional (FMI) vistos en la clase anterior, pero acotados para los años 2000 a 2023.

data <- readr::read_csv("Data/Data_FMI.csv")

data <- data |> 
  dplyr::filter(Año >= 2000, Año <= 2023)

Mi primer gráfico

Vamos a ilustrar el primer gráfico utilizando un diagrama de dispersión (scatter plot) que muestra la relación entre el crecimiento del PIB real (rgrowth) y la inflación (Inflacion) de Bolivia. En primer lugar, definimos el conjunto de datos:

data_bol <- data |> 
  filter(Pais == 'Bolivia')


ggplot(data = data_bol)

Pasar la función ggplot() crea una especie de lienzo vacío. Es decir, la primera capa sobre la cual ser irán agregando otras capas.

Mi primer gráfico

Vamos a ilustrar el primer gráfico utilizando un diagrama de dispersión (scatter plot) que muestra la relación entre el crecimiento del PIB real (rgrowth) y la inflación (Inflacion) de Bolivia. En primer lugar, definimos el conjunto de datos:

data_bol <- data |> 
  filter(Pais == 'Bolivia')


ggplot(data = data_bol,
       mapping = aes(x = rgrowth, y = Inflacion))

Al indicar las variables que queremos graficar dentro de la función ggplot, estamos mapeando las variables a los ejes X e Y de forma global. Esto se hace dentro de la función aes() (aesthetics).

Mi primer gráfico

Vamos a ilustrar el primer gráfico utilizando un diagrama de dispersión (scatter plot) que muestra la relación entre el crecimiento del PIB real (rgrowth) y la inflación (Inflacion) de Bolivia. En primer lugar, definimos el conjunto de datos:

data_bol <- data |> 
  filter(Pais == 'Bolivia')


ggplot(data = data_bol,
       mapping = aes(x = rgrowth, y = Inflacion)) +
  geom_point()

Al agregar geom_point(), estamos especificando que queremos un gráfico de puntos (scatter plot). Esta es una de las muchas geometrías disponibles en ggplot2.






Advertencia

Para encadenar funciones en R hemos utilizado el operador %>% o |>, que es el operador pipe. Sin embargo, cuando utilizamos ggplot2, no es necesario utilizar este operador, sino que las funciones se encadenan con el símbolo +. La idea es que cada función agrega una capa al gráfico, y el símbolo + indica que estamos sumando una nueva capa al gráfico existente.

Mapeo global y local

Supongamos que nos gustaría agregar un color a los puntos según otra variable, por ejemplo, Año. Para ello, podemos mapear la estética dentro de aes() de geom_point():

ggplot(data = data_bol,
       mapping = aes(x = rgrowth, y = Inflacion)) +
  geom_point(
    mapping = aes(color = Año)
  )

  • ¿Qué sucedió? De igual manera podríamos haber mapeado la estética dentro de ggplot(). La diferencia es que al hacerlo dentro de geom_point(), el mapeo se aplica solo a los puntos, mientras que si lo hacemos en ggplot(), se aplica a todo el gráfico.
  • Existen también otras formas de modificar las estéticas de los gráficos, como shape, size, alpha, etc.

Estéticas disponibles

  • Supongamos que queremos cambiar el tamaño, size de los puntos. Como esto lo queremos hacer todos y no en función de una variable, lo hacemos directamente en geom_point():
ggplot(data = data_bol,
       mapping = aes(x = rgrowth, y = Inflacion)) +
  geom_point(size = 3)

  • Quizás, también me gustaría cambiar la transparencia de los puntos o, dicho de otra manera, la luminosidad de los mismos. Para ello, podemos utilizar el parámetro alpha:
ggplot(data = data_bol,
       mapping = aes(x = rgrowth, y = Inflacion)) +
  geom_point(size = 3, alpha = 0.4)

Estéticas disponibles

Existe una amplia variedad de estéticas que podemos utilizar para personalizar nuestros gráficos en ggplot2. Algunas de las más comunes son:

Estética Descripción
x Variable eje horizontal
y Variable eje vertical
color Color de los puntos o líneas
shape Forma de los puntos
size Tamaño de los puntos
alpha Transparencia (0 a 1)
fill Color de relleno (para barras, cajas, áreas)

Dependiendo del tipo de gráfico, algunas estéticas pueden no ser aplicables. Por ejemplo, shape solo tiene sentido para gráficos de puntos.

Geometrías

En ggplot2, las geometrías son las formas en que los datos se representan visualmente. Cada geometría corresponde a un tipo de gráfico específico y se define mediante funciones que comienzan con geom_.

Geometrías comunes

ggplot2 ofrece una amplia variedad de geometrías para crear diferentes tipos de gráficos. Algunas de las más comunes son:

Geometría Descripción
geom_point() Gráfico de dispersión (scatter plot)
geom_line() Gráfico de líneas
geom_bar() Gráfico de barras
geom_histogram() Histograma
geom_boxplot() Diagrama de caja (box plot)
geom_area() Gráfico de área
geom_smooth() Línea de tendencia (regresión)

La elección de la geometría depende del tipo de datos y del mensaje que queremos transmitir con el gráfico.

Gráficos de líneas

Para crear un gráfico de líneas, utilizamos geom_line().

  • Por ejemplo, si queremos graficar el crecimiento del PIB real a lo largo de los años en Bolivia:
ggplot(data = data_bol,
       mapping = aes(x = Año, y = rgrowth)) +
  geom_line()

  • Podemos agregar más detalles al gráfico, como el color de la línea, el tamaño y el tipo de línea:
ggplot(data = data_bol,
       mapping = aes(x = Año, y = rgrowth)) +
  geom_line(color = "steelblue", linewidth = 2, linetype = "dotted")

Gráficos de barras

Supongamos que se desea saber qué continene ha crecido más en términos de PIB real el 2023. Para ello, podemos utilizar geom_bar(), luego de aplicar algunas transformaciones a los datos:

data |> 
  filter(Año == 2023) |>
  group_by(Continent) |>
  summarise(rgrowth = mean(rgrowth, na.rm = TRUE)) |>
  ggplot(mapping = aes(x = Continent, y = rgrowth)) +
  geom_bar(stat = "identity") 

  • En ggplot2, cada geom_*() aplica por defecto una estadística (stat) que transforma los datos antes de graficarlos.

  • Por ejemplo, geom_bar() normalmente cuenta el número de observaciones por categoría (stat = "count").

  • Al usar stat = "identity", le indicamos que los valores de y ya están calculados y deben representarse tal cual.

Histogramas

Los histogramas son útiles para visualizar la distribución de una variable continua. Para crear un histograma, utilizamos geom_histogram().

Por ejemplo, si queremos ver la distribución del crecimiento del PIB real el 2023:

data |> 
  filter(Año == 2023) |>
  ggplot(mapping = aes(x = rgrowth)) +
  geom_histogram()

Podemos ajustar el número de barras (bins) con parámetro bins, el color con color y el relleno con fill:

data |> 
  filter(Año == 2023) |>
  ggplot(mapping = aes(x = rgrowth)) +
  geom_histogram(bins = 50,  fill = "steelblue", color = "black")

Mejorando los gráficos

Para que nuestros gráficos sean más informativos y visualmente atractivos, podemos agregar títulos, etiquetas a los ejes, leyendas y otros elementos.

Facetas

Las facetas permiten dividir un gráfico en múltiples paneles según una o más variables categóricas. Esto es útil para comparar subgrupos dentro de los datos. Por ejemplo, supongamos que se quiere ver el histograma del crecimiento del PIB real por continente. Podemos utilizar facet_wrap() para esto:

data |> 
  filter(Año == 2023) |>
  ggplot(mapping = aes(x = rgrowth)) +
  geom_histogram(bins = 40, fill = "steelblue") +
  facet_wrap(~ Continent)

  • Aquí, facet_wrap(~ Continent) crea un panel separado para cada continente, permitiendo comparar la distribución del crecimiento del PIB real entre ellos.

  • Las facetas son especialmente útiles cuando se trabaja con grandes conjuntos de datos y se desea explorar patrones en subgrupos específicos.

  • Algunos argumentos adicionales son ncol y nrow, que permiten especificar el número de columnas y filas en las facetas, respectivamente.

Títulos

Podemos agregar un título al gráfico utilizando labs(). Para ilustrar, utilizamos el gráfico de barras que muestra el crecimiento del PIB real promedio por continente en 2023:

data |> 
  filter(Año == 2023) |>
  group_by(Continent) |>
  summarise(rgrowth = mean(rgrowth, na.rm = TRUE)) |>
  ggplot(mapping = aes(x = Continent, y = rgrowth)) +
  geom_bar(stat = "identity") +
  labs(
    title = "Crecimiento del PIB real promedio por continente en 2023",
    subtitle = "El crecimiento del PIB real se refiere al incremento en la producción de bienes y servicios",
    x = "Continente",
    y = "Crecimiento del PIB real (%)",
  )

Temas

Los temas (themes) en ggplot2 permiten personalizar la apariencia general del gráfico, incluyendo el fondo, las cuadrículas, las fuentes y otros elementos visuales.

Podemos aplicar un tema predefinido utilizando theme_minimal(), theme_bw(), entre otros. Por ejemplo:

data |> 
  filter(Año == 2023) |>
  group_by(Continent) |>
  summarise(rgrowth = mean(rgrowth, na.rm = TRUE)) |>
  ggplot(mapping = aes(x = Continent, y = rgrowth)) +
  geom_bar(stat = "identity") +
  labs(
    title = "Crecimiento del PIB real promedio por continente en 2023",
    subtitle = "El crecimiento del PIB real se refiere al incremento en la producción de bienes y servicios",
    x = "Continente",
    y = "Crecimiento del PIB real (%)") +
  theme_minimal()

Temas

Los temas (themes) en ggplot2 permiten personalizar la apariencia general del gráfico, incluyendo el fondo, las cuadrículas, las fuentes y otros elementos visuales.

Podemos aplicar un tema predefinido utilizando theme_minimal(), theme_bw(), entre otros. Por ejemplo:

data |> 
  filter(Año == 2023) |>
  group_by(Continent) |>
  summarise(rgrowth = mean(rgrowth, na.rm = TRUE)) |>
  ggplot(mapping = aes(x = Continent, y = rgrowth)) +
  geom_bar(stat = "identity") +
  labs(
    title = "Crecimiento del PIB real promedio por continente en 2023",
    subtitle = "El crecimiento del PIB real se refiere al incremento en la producción de bienes y servicios",
    x = "Continente",
    y = "Crecimiento del PIB real (%)") +
  theme_bw()

Temas

Los temas (themes) en ggplot2 permiten personalizar la apariencia general del gráfico, incluyendo el fondo, las cuadrículas, las fuentes y otros elementos visuales.

Podemos aplicar un tema predefinido utilizando theme_minimal(), theme_bw(), entre otros. Por ejemplo:

data |> 
  filter(Año == 2023) |>
  group_by(Continent) |>
  summarise(rgrowth = mean(rgrowth, na.rm = TRUE)) |>
  ggplot(mapping = aes(x = Continent, y = rgrowth)) +
  geom_bar(stat = "identity", 
           fill = 'green') +
  labs(
    title = "Crecimiento del PIB real promedio por continente en 2023",
    subtitle = "El crecimiento del PIB real se refiere al incremento en la producción de bienes y servicios",
    x = "Continente",
    y = "Crecimiento del PIB real (%)") +
  theme_dark()

Temas

Finalmente, los temas predefinidos permiten controlar, de forma general, el tipo de letra o el tamaño de la fuente. Por ejemplo:

data |> 
  filter(Año == 2023) |>
  group_by(Continent) |>
  summarise(rgrowth = mean(rgrowth, na.rm = TRUE)) |>
  ggplot(mapping = aes(x = Continent, y = rgrowth)) +
  geom_bar(stat = "identity") +
  labs(
    title = "Crecimiento del PIB real promedio por continente en 2023",
    subtitle = "El crecimiento del PIB real se refiere al incremento en la producción de bienes y servicios",
    x = "Continente",
    y = "Crecimiento del PIB real (%)") +
    theme_bw(base_size = 12, 
            base_family = "Times New Roman") 

Más sobre temas

Ahora, podemos personalizar aún más el tema utilizando theme(). Por ejemplo, podemos cambiar el tamaño de la fuente, el color, o el tipo de letra, siempre y cuando esté registrada en el sistema y en R:

data |> 
  filter(Año == 2023) |>
  group_by(Continent) |>
  summarise(rgrowth = mean(rgrowth, na.rm = TRUE)) |>
  ggplot(mapping = aes(x = Continent, y = rgrowth)) +
  geom_bar(stat = "identity") +
  labs(
    title = "Crecimiento del PIB real promedio por continente en 2023",
    subtitle = "El crecimiento del PIB real se refiere al incremento en la producción de bienes y servicios",
    x = "Continente",
    y = "Crecimiento del PIB real (%)") +
    theme_bw(base_size = 12, 
            base_family = "Times New Roman") +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold", size = 18),
    plot.subtitle = element_text(hjust = 0.5, size = 12),
    axis.title.x = element_text(face = "bold", size = 14),
    axis.title.y = element_text(face = "bold", size = 14),
    axis.text.x = element_text(size = 14),
    axis.text.y = element_text(size = 14)
  )

Conclusiones

  • ggplot2 es una herramienta poderosa para la visualización de datos en R, basada en la gramática de gráficos.
  • Permite crear gráficos de forma sistemática y flexible, utilizando capas para agregar elementos visuales.
  • La personalización de gráficos es sencilla, utilizando funciones como labs(), theme(), y diferentes geometrías.
  • Existen muchas geometrías y estéticas disponibles para crear gráficos variados y adaptados a las necesidades de análisis que no se han visto en esta clase. Por ejemplo, geom_text() para agregar texto o scale_*() para personalizar escalas de colores, tamaños, etc.