Visualización de datos en R

Elena Quintero

13/01/2025

Carpeta con material


https://rstats-courses.github.io/CursoR-AEET-2025/materiales.html

Exploración de datos

La exploración de datos nos permite verificar su calidad, generar y probar hipótesis de forma rápida, identificando pistas prometedoras para analizar más a fondo luego.

La visualización de los datos es un buen comienzo, pero por sí sola no suele ser suficiente, ya que a menudo requiere transformar los datos previamente.

https://r4ds.had.co.nz/explore-intro.html

Beneficios de usar ggplot

  • Reproducible

  • Consistencia gramática

  • Muy flexible y permite controlar gran cantidad de detalles

  • Fácil para uso básico

  • Comunidad de usuarios activos

Laura Navarro | code here

Cédric Scherer | code here

Cédric Scherer

Timo Grossenbacher | code here

Cédric Scherer | code here

aRtsy: Generative Art with R and ggplot2

Gramática de ggplot

Basado en la gramática layered grammar of graphics - Bertin 1983, Wilkinson et al. 2005, Wickham 2010.

Illustration QCBS R workshop series

Capas

  • Data - dataset a graficar; necesita formato tidy data

  • Aesthetics - describe cómo se asignan las variables del dataset (y sus escalas) a las propiedades visuales (x, y, size, colour, fill, group, sise, shape. . . )

  • Geometries - determina la forma de representar los datos (geoms: points, lines, bars, boxplot. . . )

  • Scales - maneja las escalas de los aesthetics (x & y format, colors continuous or discrete, sizes, shapes. . . )

  • Facets - crea subplots (facet_wrap or facet_grid. . . )

  • Themes - apariencia general del gráfico, no ligada a los datos (title, x.axis.text, legend. . . )

  • Statistics - resume los datos con estadísticos. Muchas veces ya va implícito en el “geom” (stats: count, density, bins, means, density. . . )

  • Coordinate system - determina el sistema de coordenadas a usar en los ejes (cartesian, polar, map projections. . . )

*Capas necesarias

Dataset

https://doi.org/10.1002/ecy.4463

Dataset

Cargar paquetes

library(here)
library(tidyverse)
library(tidylog)

Leer datos

dt <- read_csv(here("data/clean_data.csv"))

Graficar

  1. Indicar el dataset
ggplot(data = dt)

Graficar

  1. Definir los aesthetics (variables a visualizar)
ggplot(data = dt, 
       aes(x = year, y = fruits))

Graficar

  1. Determinar la forma de representar los datos con GEOMs
ggplot(data = dt, 
       aes(x = year, y = fruits)) +
  geom_point()

Ajustar detalles de visualizacion

ggplot(dt, 
       aes(x = year, y = fruits)) +
  geom_point(color = "coral") 

Ajustar detalles de visualizacion

ggplot(dt, 
       aes(x = year, y = fruits)) +
  geom_point(color = "coral",
             shape = "triangle",
             size = 4, 
             alpha = 0.5) 

Valores de los aesthetics (aes):

Ajustar detalles de visualizacion

ggplot(dt, 
       aes(x = year, y = fruits, 
           color = pollinator_code)) +
  geom_point(shape = "triangle",
             size = 4, 
             alpha = 0.5) 

Ajustar detalles de visualizacion

ggplot(dt, 
       aes(x = year, y = fruits, 
           color = year)) +
  geom_point() 

Escalas

Van refereridas a las variables o aethetics (aes):

  • X e Y
  • Tamaño de punto (size), de linea (linewidth)
  • Forma de punto (shape) y de linea (linetype)
  • Color y relleno (colour, fill)

Escalas - X, Y

ggplot(dt, 
       aes(x = year, y = fruits, 
           color = year)) +
  geom_point() +
  scale_x_continuous(n.breaks = 3)

Escalas - X, Y

ggplot(dt, 
       aes(x = year, y = fruits, 
           color = year)) +
  geom_point() +
  scale_x_continuous(n.breaks = 3) + 
  scale_y_continuous(
          breaks = c(100000, 200000),
          labels = c("100mil",
                     "200mil"))

Escalas - X, Y

ggplot(dt, 
       aes(x = year, y = fruits, 
           color = year)) +
  geom_point() +
  scale_y_reverse()

Escalas - Tamaño

ggplot(dt, 
       aes(x = year, y = fruits, 
           color = year,
           size = year)) +
  geom_point() +
  scale_size_binned(range = c(0.1, 8),
                    n.breaks = 10)

Escalas - Color (discreto)

ggplot(dt, 
       aes(x = year, y = fruits, 
           color = fleshy_fruit)) +
  geom_point() +
  scale_color_manual(
      values = c("darkolivegreen3", 
                 "coral2"))

Escalas - Color (continuo)

ggplot(dt, 
       aes(x = year, y = fruits, 
           color = year)) +
  geom_point() +
  scale_color_gradient(
    low = "yellow", high = "orange")

Escalas - Color

ggplot(dt, 
       aes(x = year, y = fruits, 
           color = year)) +
  geom_point() +
  scale_color_viridis_c()

Escalas - Color

Paletas de color:

Facets

  • facet_wrap()
  • facet_grid()

Facets

dt |> 
  group_by(year, site) |> 
  summarise(mean_fruits = mean(fruits, 
                    na.rm = TRUE)) |> 
  ggplot(aes(x = year, 
             y = mean_fruits)) +
  geom_point() +
  geom_line() +
  facet_wrap(~site, scales = "free")

Facets

dt |> 
  group_by(year, site, pollinator_code) |> 
  summarise(mean_fruits = mean(fruits, 
                    na.rm = TRUE)) |> 
  ggplot(aes(x = year, 
             y = mean_fruits)) +
  geom_point() +
  geom_line() +
  facet_grid(site~pollinator_code, 
             scales = "free")

Tipos de Geoms

 [1] "geom_abline"            "geom_area"              "geom_bar"              
 [4] "geom_bin_2d"            "geom_bin2d"             "geom_blank"            
 [7] "geom_boxplot"           "geom_col"               "geom_contour"          
[10] "geom_contour_filled"    "geom_count"             "geom_crossbar"         
[13] "geom_curve"             "geom_density"           "geom_density_2d"       
[16] "geom_density_2d_filled" "geom_density2d"         "geom_density2d_filled" 
[19] "geom_dotplot"           "geom_errorbar"          "geom_errorbarh"        
[22] "geom_freqpoly"          "geom_function"          "geom_hex"              
[25] "geom_histogram"         "geom_hline"             "geom_jitter"           
[28] "geom_label"             "geom_line"              "geom_linerange"        
[31] "geom_map"               "geom_path"              "geom_point"            
[34] "geom_pointrange"        "geom_polygon"           "geom_qq"               
[37] "geom_qq_line"           "geom_quantile"          "geom_raster"           
[40] "geom_rect"              "geom_ribbon"            "geom_rug"              
[43] "geom_segment"           "geom_sf"                "geom_sf_label"         
[46] "geom_sf_text"           "geom_smooth"            "geom_spoke"            
[49] "geom_step"              "geom_text"              "geom_tile"             
[52] "geom_violin"            "geom_vline"            

Tipos de Geoms

Subset de los datos

Seleccionar datos con información para diámetro de tronco. Sólo hay informacion para el sitio llamado “AND”.

dt_diam <- dt |> filter(!is.na(stem_cm))
filter: removed 80,777 rows (98%), 1,503 rows remaining

Geoms - Líneas verticales y horizontales

ggplot(dt_diam, 
       aes(x = stem_cm, y = fruits)) +
  geom_point() +
  geom_hline(yintercept = 700,
             size = 2) +
  geom_vline(xintercept = c(50, 120), 
          color = c("red", "blue"))

Geoms - Líneas de tendencia

ggplot(dt_diam, 
       aes(x = stem_cm, y = fruits)) +
  geom_point() +
  geom_smooth()

Geoms - Líneas de tendencia

ggplot(dt_diam, 
       aes(x = stem_cm, y = fruits)) +
  geom_point() +
  geom_smooth(method = "lm")

Geoms - Líneas de tendencia

ggplot(dt_diam, 
       aes(x = stem_cm, y = fruits, 
           color = shade_tolerance)) +
  geom_point(alpha = 0.5) +
  geom_smooth(method = "lm")

Geoms - Histograma

ggplot(dt_diam, 
       aes(x = stem_cm)) +
  geom_histogram()

Geoms - Histograma

ggplot(dt_diam, 
       aes(x = stem_cm)) +
  geom_histogram(bins = 10)

Geoms - Densidad

ggplot(dt_diam, 
       aes(x = stem_cm)) +
  geom_density()

Geoms - Densidad

ggplot(dt_diam, 
       aes(x = stem_cm)) +
  geom_density(bw = 1)

Geoms - Barras

Contar número de casos: stat = "count"

ggplot(dt_diam,
         aes(x = species_name)) +
  geom_bar(stat = "count")

Geoms - Barras

Para datos resumidos - alternativa 1:

Usar valores ya calculados: stat = "identity"

dt_diam |> 
  group_by(species_name) |>
  summarise(mean_stem = mean(stem_cm)) |> 
  ggplot(aes(x = species_name,
             y = mean_stem)) +
  geom_bar(stat = "identity")

Geoms - Barras

Para datos resumidos - alternativa 2:

Calcular valores dentro de ggplot: stat = "summary"

ggplot(dt_diam, 
       aes(x = species_name, 
           y = stem_cm)) +
  geom_bar(stat = "summary", 
           fun = "mean")

Geoms - Boxplot

ggplot(dt_diam, 
       aes(x = species_name, 
           y = stem_cm)) +
  geom_boxplot()

Geoms - Violin y puntos

ggplot(dt_diam, 
       aes(x = species_name, 
           y = stem_cm)) +
  geom_violin() + 
  geom_jitter(alpha = 0.5)

Geoms - Violin y puntos

Ordernar eje de la X en base a valores del eje de la Y

ggplot(dt_diam, 
 aes(x = reorder(species_name, stem_cm), 
     y = stem_cm)) +
  geom_violin() + 
  geom_jitter(alpha = 0.5)

Themes

Themes

ggplot(dt_diam, 
       aes(x = reorder(species_name, stem_cm), 
           y = stem_cm)) +
  geom_violin() + 
  geom_jitter(alpha = 0.5) + 
  theme_linedraw()

Themes

ggplot(dt_diam, 
       aes(x = reorder(species_name, stem_cm), 
           y = stem_cm)) +
  geom_violin() + 
  geom_jitter(alpha = 0.5) + 
  theme_linedraw() + 
  theme(axis.text.x = element_text(
          angle = 90, 
          hjust = 1, vjust = 0.5,
          face = "italic"))

Themes

ggplot(dt_diam, 
       aes(x = reorder(species_name, stem_cm), 
           y = stem_cm)) +
  geom_violin() + 
  geom_jitter(alpha = 0.5) + 
  theme_linedraw() + 
  theme(axis.text.x = element_text(
          angle = 90, 
          hjust = 1, vjust = 0.5,
          face = "italic"),
        axis.text.y = element_text(
          size = 15, face = "bold"))

Themes

ggplot(dt_diam, 
       aes(x = reorder(species_name, stem_cm), 
           y = stem_cm)) +
  geom_violin() + 
  geom_jitter(alpha = 0.5) + 
  theme_linedraw() + 
  theme(axis.text.x = element_text(
          angle = 90, 
          hjust = 1, vjust = 0.5,
          face = "italic"),
        axis.text.y = element_text(
          size = 15, face = "bold")) +
  labs(x = NULL, 
       y = "Stem diameter (cm)", 
       title = "Diameter of Pinaceae species in USA National Parks")

Themes

Para fijar un tema que se aplique a todos los gráficos:

theme_set(theme_minimal())


Existen muchos paquetes con temas predeterminados. Muchos también vienen con especificaciones para las escalas de los aesthetics (scales). Ejemplos:

library(hrbrthemes)
library(ggthemes)
library(ggpomological)
library(tvthemes)
library(ggtech)
library(ggthemr)
library(ggsci)

library(ggThemeAssist) es una addin de RStudio que ayuda a cambiar la apariencia de los temas. https://github.com/calligross/ggthemeassist

Composición de figuras

library(patchwork)

Composición de figuras

Nombrar los plots como objetos

library(patchwork)

p1 <- ggplot(dt_diam,
       aes(x = stem_cm,
           fill = genus)) +
  geom_density(alpha = 0.3)

p2 <- ggplot(dt,
       aes(x = stem_cm,
           fill = shade_tolerance)) +
  geom_density(alpha = 0.3)

p1 + p2 + 
  plot_annotation( 
  title = "Diameter distribution",
  tag_levels = 'A')

Composición de figuras

Guardar gráficos

ggsave(p1, width = 20, units = "cm", 
  filename = here("img/figure_1.pdf"))

Argumentos:

  • width
  • height
  • units = (“in”, “cm”, “mm”, “px”)
  • device = (“png”, “pdf,”jpeg”, “tiff”, “svg”…)

Otros paquetes útiles

library(ggdist) - graficar datos con distribuciones amplias (ej. Bayes posteriors).

https://mjskay.github.io/ggdist/

Otros paquetes útiles

library(ggrepel) - etiquetar datos

https://cran.r-project.org/web/packages/ggrepel/vignettes/ggrepel.html

Otros paquetes útiles

library(GGally) - exploración de datos y relación entre variables.

GGally::ggpairs(dataset)

https://github.com/ggobi/ggally

Otros paquetes útiles

library(gganimate) - animar gráficos

https://gganimate.com/

Otros paquetes útiles

library(ggtext) -

https://github.com/wilkelab/ggtext

Otros paquetes útiles

library(ggforce) - resaltar características de los datos.

https://github.com/thomasp85/ggforce

Más extensiones de GGplot


https://github.com/erikgahner/awesome-ggplot2
https://exts.ggplot2.tidyverse.org/gallery/

Recursos

Ejercicio 1

Con el dataset completo (dt) genera un violin plot del número de frutos por m2 (fruits) en escala logarítmica para los distintos tipos de crecimiento (growth_form)

Ejercicio 1

Con el dataset completo (dt) genera un violin plot del número de frutos por m2 (fruits) en escala logarítmica para los distintos tipos de crecimiento (growth_form)

ggplot(dt, 
       aes(x = growth_form, 
           y = fruits)) +
  geom_violin() + 
  labs(x = "Tipo de crecimiento", 
       y = "Fruits per m2 (log scale)") + 
  scale_y_log10()

Ejercicio 2

Para las distintas especies del género Quercus, sacar una tendencia del número de frutos por m2 a lo largo de los años.

Ejercicio 2

Para las distintas especies del género Quercus, sacar una tendencia del número de frutos por m2 a lo largo de los años.

dt |> filter(genus == "Quercus") |> 
  ggplot(aes(x = year, 
             y = fruits,
             color = species_name)) +
  geom_point(alpha = 0.4)  +
  geom_smooth() +
  scale_color_viridis_d() + 
  labs(x = "Year", 
       y = "Fruits per m2",
       color = "Quercus sp.")

Ejercicio 2

dt |> filter(genus == "Quercus") |> 
  ggplot(aes(x = year, 
             y = fruits,
             color = species_name)) +
  geom_point(alpha = 0.4, size = 2) + 
  geom_smooth() +
  scale_color_viridis_d() + 
  facet_wrap(~species_name, scales = "free", nrow = 1) +
  theme(legend.position = "none",
        axis.text.x = element_text(angle = 60, hjust = 1), 
        strip.text = element_text(face = "italic")) +
  labs(x = "Year", 
       y = "Fruits per m2")

Ejercicio 2

Ejercicio 3

Replica las gráficas de esta figura (lo más similar posible):

Ejercicio 3

Alternativa 1 - Sacar primero la media y la SE del número de frutos y luego graficar

dt |> 
  #remove outlier year
  filter(!(site == "BNZ" & year == 1958)) |> 
  group_by(site, year) |> 
  summarise(mean_fruits = mean(fruits, na.rm = TRUE),
            se_fruits = sd(fruits, na.rm = TRUE)/sqrt(n())) |> 
  ggplot(aes(x = year, y = mean_fruits)) +
  geom_point() +
  geom_errorbar(aes(ymin = mean_fruits - se_fruits,
                    ymax = mean_fruits + se_fruits)) +
  geom_line() + 
  facet_wrap(~site, scales = "free") + 
  theme_bw()

Ejercicio 3

Alternativa 2 - Sacar la media y la SE de los frutos dentro de ggplot

dt |> 
  #remove outlier year
  filter(!(site == "BNZ" & year == 1958)) |> 
  ggplot(aes(x = year, y = fruits)) +
  geom_point(stat = "summary", fun = "mean") +
  geom_line(stat = "summary", fun = "mean") +
  stat_summary(
    fun.data = "mean_se", 
    geom = "errorbar",
    width = 0.2) + 
  facet_wrap(~site, scales = "free") + 
  theme_bw()