Interactividad
en tablas y gráficos

Añadiendo interactividad a documentos Quarto


Introducción

En esta sesión veremos cómo podemos utilizar Quarto para crear documentos interactivos que incorporan tablas y gráficos que permiten la exploración de los datos.

Paso 1 - Tablas

El primer paso en la preparación de cualquier análisis es abrir los datos. En este ejemplo utilizaremos el conjunto de datos world del paquete poliscidata, que contiene información sobre diferentes países y sus niveles de democracia.

Podríamos recurrir a otros paquetes y funciones que abrieran archivos en R para cargar datos. No obstante, para efectos de demostración, resulta más fácil emplear datos disponibles en algún paquete de R. El paquete poliscidata contiene datos sobre los países del mundo y sobre los estados de EE.UU. Se tratan de datos de interés para politólogos, de modo que nos facilitan la vida.

El código abajo carga los datos del paquete poliscidata y los almacena en un data frame llamado w. Luego, utiliza la función reactable del paquete reactable para crear una tabla interactiva que muestra algunas columnas seleccionadas del data frame w. La tabla permite ordenar, redimensionar y buscar en los datos.

Code
# Carga los datos del paquete
# poliscidata con datos de 
# ciencia política
# Si no lo tienes instalado,
# pudes hacerlo con:
# install.packages("poliscidata")
library(poliscidata)

w <- world


# Usar la función reactable
# para visualizar los datos
library(reactable)

reactable(w[, c("country", "dem_level4", "regime_type3","pop_total")],
          sortable = T, 
          resizable = T, 
          searchable = T)

Reactable

La clave aquí está en el paquete reactable. Posee una enorme capacidad de configuración y personalización, como la inclusión de mini-gráficos en las columnas, el uso de imágenes, entre otras funcionalidades muy útiles, como la posibilidad de ordenar, filtrar o buscar valores, así como de cambiar el ancho de las columnas.

Miremos la página de Reactable para conocer más sobre cómo podemos crear tablas interactivas de distintos formatos en R y Quarto.

Reactablefmtr

Si reactable ya era muy potente, el paquete reactablefmtr lo lleva a otro nivel. Este paquete extiende las funcionalidades de reactable y permite crear tablas aún más personalizadas e interactivas. Con reactablefmtr, podemos agregar barras de progreso, mini-gráficos y otros elementos visuales a nuestras tablas.

Code
# install.packages("reactablefmtr")

library(reactablefmtr)

dt <-   w[1:10, c("country", "dem_level4", "regime_type3","pop_total")]

# Crear una tabla con reactablefmtr
reactable(
   dt,
   defaultColDef = colDef(
    cell = data_bars(dt, text_position = "outside-base")
  )
)

KableExtra

Otro paquete muy útil para crear tablas en R y Quarto es kableExtra. Este paquete permite crear tablas con un formato atractivo y personalizable. Aunque no es tan interactivo como reactable, kableExtra ofrece muchas opciones para mejorar la apariencia de las tablas.

Code
library(kableExtra)

# Crear una tabla con kableExtra
kable(w[1:10, c("country", "dem_level4", "regime_type3","pop_total")]) |>
  kable_classic(full_width = F, html_font = "Cambria")
country dem_level4 regime_type3 pop_total
Afghanistan Authoritarian Dictatorship 29.1
Albania Hybrid Parliamentary democ 3.2
Algeria Authoritarian Dictatorship 35.4
Angola Authoritarian Dictatorship 19.0
Argentina Part Democ Presidential democ 40.7
Armenia Hybrid NA 3.1
Australia Full Democ Parliamentary democ 21.5
Austria Full Democ Parliamentary democ 8.4
Azerbaijan Authoritarian Dictatorship 8.9
Bahrain Authoritarian Dictatorship 0.8

Resulta especialmente útil para crear tablas que puedan ser exportadas tanto a pdfs como a html.

GT

Otro paquete interesante para crear tablas en R es gt. Este paquete permite crear tablas con un formato atractivo y personalizable, similar a kableExtra. Además, gt ofrece funcionalidades adicionales para agregar títulos, subtítulos y pies de página a las tablas. Se trata del niño bonito de las tablas, porque se incluye en tidyverse. Ah, tidyverse…

Si queréis podéis mirarlo, pero yo prefiero las dos versiones anteriores.

DT

El paquete DT es otra opción popular para crear tablas interactivas en R. Basado en la biblioteca JavaScript DataTables, DT permite crear tablas con funcionalidades como paginación, búsqueda y ordenamiento. Es una opción sólida para quienes buscan interactividad en sus tablas.

No es tan adaptable como reactable, pero es una buena opción si ya estás familiarizado con DataTables.

Code
library(DT)

# Crear una tabla con DT
datatable(w[, c("country", "dem_level4", "regime_type3","pop_total")],
          options = list(pageLength = 5, 
                         autoWidth = TRUE))

Stargazer

Para los que trabajan con modelos estadísticos, el paquete stargazer es una herramienta útil para crear tablas de resumen de modelos. Aunque no es interactivo, stargazer facilita la presentación de resultados de modelos en un formato claro y profesional. Básicamente, coge los resultados de los métodos estadísticos y los convierte en una tabla formatada como se debe.

Code
library(stargazer)

# Crear una tabla de resumen de modelos con stargazer
model1 <- lm(pop_total ~ dem_level4 + regime_type3, data = w)

model2 <- lm(pop_total ~ dem_level4, data = w)

stargazer(model1, model2, type = "html",
          title = "Resumen de Modelos",
          dep.var.labels = "Población Total",
          covariate.labels = c("Nivel de Democracia", "Tipo de Régimen"),
          out = "model_summary.html")
Resumen de Modelos
Dependent variable:
Población Total
(1) (2)
Nivel de Democracia 30.895 10.536
(46.351) (36.122)
Tipo de Régimen 8.882 -11.065
(53.505) (37.858)
dem_level4Authoritarian 45.125 13.678
(61.225) (36.010)
regime_type3Parliamentary democ 31.899
(48.999)
regime_type3Presidential democ 18.086
(44.121)
Constant 7.213 36.562
(57.604) (29.787)
Observations 133 166
R2 0.010 0.005
Adjusted R2 -0.029 -0.014
Residual Std. Error 163.336 (df = 127) 145.924 (df = 162)
F Statistic 0.246 (df = 5; 127) 0.253 (df = 3; 162)
Note: p<0.1; p<0.05; p<0.01

Ejercicios

  1. Crea una tabla interactiva utilizando el paquete reactable que muestre las columnas country, dem_level4, regime_type3 y gdp_per_capita del data frame w. Asegúrate de que la tabla sea ordenable, redimensionable y buscable.
Code
# Solución
reactable(w[, c("country", "dem_level4", "regime_type3", "gdp_per_capita")],
          sortable = T, 
          resizable = T, 
          searchable = T)
  1. Utiliza el paquete reactablefmtr para crear una tabla que incluya barras de progreso en la columna gdp_per_capita. ¿Cómo puedes personalizar la apariencia de las barras?
Code
# Solución
library(reactablefmtr)

dt <-   w[1:10, c("country", "dem_level4", "regime_type3","gdp_per_capita")]

# Crear una tabla con reactablefmtr
reactable(
   dt,
   defaultColDef = colDef(
    cell = data_bars(dt, text_position = "outside-base")
  )
)
  1. Crea una tabla utilizando el paquete kableExtra que muestre las primeras 10 filas del data frame w con las columnas country, dem_level4, regime_type3 y pop_total. Aplica un estilo clásico a la tabla.
Code
# Solución
library(kableExtra)

kable(w[1:10, c("country", "dem_level4", "regime_type3","pop_total")]) |>
  kable_classic(full_width = F, html_font = "Cambria")

Paso 2 - Gráficos

Lo más habitual es que los gráficos en R y Quarto sean estáticos. Sin embargo, existen paquetes que permiten crear gráficos interactivos, lo que puede mejorar la experiencia del usuario al explorar los datos. Son varios paquetes los que permiten crear gráficos interactivos en R. A continuación, echemos un vistazo a algunos:

  • ggiraph: Este paquete extiende las capacidades de ggplot2 para crear gráficos interactivos. Permite agregar interactividad a los elementos del gráfico, como puntos, líneas y barras, mediante la función girafe(). Los gráficos creados con ggiraph pueden incluir tooltips, enlaces y otras funcionalidades interactivas. Documentación aquí.

  • plotly: Plotly es una biblioteca de gráficos interactivos que se integra bien con R. Permite crear gráficos interactivos a partir de ggplot2 utilizando la función ggplotly(). Los gráficos de Plotly son altamente personalizables y pueden incluir zoom, desplazamiento y otras interacciones. Documentación aquí.

  • networkD3: Este paquete se utiliza para crear gráficos de redes interactivas. Permite visualizar relaciones entre nodos y enlaces de manera interactiva, lo que es útil para analizar datos de redes sociales, biológicas y otras estructuras de red. Documentación aquí.

  • highcharter: Highcharter es un paquete que proporciona una interfaz para la biblioteca de gráficos Highcharts. Permite crear gráficos interactivos con una amplia variedad de tipos de gráficos, como líneas, barras, áreas y más. Los gráficos de Highcharter son altamente personalizables y pueden incluir animaciones y otras interacciones. Documentación aquí.

  • leaflet: Este paquete se utiliza para crear mapas interactivos en R. Permite agregar capas de datos, marcadores y otras funcionalidades interactivas a los mapas, lo que es útil para visualizar datos geoespaciales. Documentación aquí.

  • r2d3: Este paquete permite integrar visualizaciones D3.js en R. D3.js es una biblioteca de JavaScript para crear gráficos interactivos y visualizaciones de datos. El paquete r2d3 facilita la creación de gráficos D3.js utilizando datos de R. Documentación aquí.

  • tenet: El paquete tenet incluye funciones específicas para crear gráficos interactivos en el contexto del análisis de texto. Permite visualizar resultados de análisis de texto de manera interactiva, facilitando la exploración y comprensión de los datos textuales. Documentación aquí. Aplicaciones a textos literarios aquí.

GGiraph

En este ejemplo, utilizaremos el paquete ggiraph para crear un gráfico interactivo que muestre la relación entre el nivel de democracia y el porcentaje de población mayor de 65 años en diferentes países. Agregaremos tooltips para proporcionar información adicional sobre cada país cuando el usuario pase el cursor sobre los puntos del gráfico.

Primero empezamos preparando los datos:

Code
wm <- w

wm$regionun <- as.character(wm$regionun)

wm$regionun[wm$regionun=="Australia/New Zealand/Oceania"] <- "Oceania"
wm$regionun[wm$regionun%in%c("Latin America/Caribbean","USA/Canada") ] <- "America"

wa <- wm[! is.na(wm$dem_level4),]
wa$religoin[wa$name=="United States"] <- "Other Christian"

wa <- wa[!is.na(wa$religoin),]
wa$frac_eth <- round(wa$frac_eth, 3)

wa$tooltip_scat <- paste0("<b>", wa$name, "</b><br>Democratic Score: ", wa$dem_score14, "<br>HDI: ", wa$hdi, "<br>Religion: ", wa$religoin)

wa$tooltip_scat2 <- paste0("<b>", wa$name, "</b><br>Democratic Score: ", wa$dem_score14, "<br>Gender Inequality Index: ", wa$gender_unequal, "<br>Region: ", wa$regionun)


wa$name <- wa$country

wa$name <- gsub("'","", wa$name, fixed = T)


dd <- data.frame(wa[,c("dem_score14","gender_unequal","frac_eth","gini10","pop_65_older","hdi",            "lifeex_total")])

dd$geometry <- NULL

# Calculate corNULL
# # Calculate correlation matrix
co <- cor(dd, use="pairwise.complete.obs")


# Reshape for ggplot2
mt <- reshape2::melt(co)
colnames(mt) <- c("Var1", "Var2", "value")

luego, creamos el gráfico normal (sin interactividad):

Code
library(ggplot2)
library(ggiraph)

p1 <- ggplot(wa, aes(x = dem_level4, y = pop_65_older, group=dem_level4, fill=dem_level4)) +
    geom_violin() +
  geom_point_interactive(aes(tooltip = paste0("<b>", name, "</b><br>Score: ", dem_score14, "<br>Pop. 65+ (%): ", pop_65_older), data_id = name)) +
  theme_minimal() +
  labs(title = "Democratic Level and Pop. 65 or Older",
       x = "Democracy Level",
       y = "Population Aged 65 or Older (%)") +
  theme(legend.position = "none", plot.title=ggtext::element_markdown(size=16, face = "bold"))+
  scale_fill_brewer(palette="Dark2", direction = 1)

p1

finalmente, añadimos la interactividad con ggiraph:

Code
girafe(ggobj = p1,
       options = list(
         opts_hover(css = "fill:yellow;r:5pt;"),
         opts_tooltip(css = "background-color:lightblue; color:black; font-size:16px; padding:5px; border-radius:5px;")
       )
)

Ejercicios

  1. Crea un gráfico interactivo utilizando ggiraph que muestre la relación entre el índice de desarrollo humano (HDI) y el puntaje democrático (dem_score14) para diferentes países. Utiliza colores para diferenciar las religiones principales (religoin) y agrega tooltips que muestren el nombre del país, el puntaje democrático y el HDI.
Code
# Solución

# Crea el tootltip
wa$tooltip_scat <- paste0("<b>", wa$name, "</b><br>Democratic Score: ", wa$dem_score14, "<br>HDI: ", wa$hdi)

# Crea el gráfico interactivo
p2 <- ggplot(wa, 
             aes(x = hdi, y = dem_score14, color = religoin, group=religoin)) +
  geom_point_interactive(aes(tooltip = tooltip_scat, data_id = name)) +
  theme_minimal() +
  theme(panel.grid.major = element_blank(),
        legend.position = "bottom",
        plot.title=ggtext::element_markdown(size=16, face = "bold")) +
  labs(y="Democratic Score", x="Human Development Indicator", title="Democracy and Human Development")+
  scale_color_brewer(palette="Dark2", direction = 1, name="Religion")

# Añade la interactividad
girafe(ggobj = p2,
       options = list(
         opts_hover(css = "fill:orange;r:5pt;"),
         opts_tooltip(css = "background-color:lightgreen; color:black; font-size:16px; padding:5px; border-radius:5px;")
       )
  1. Genera un scatter plot interactivo utilizando ggiraph que muestre la relación entre el puntaje democrático (dem_score14) y el índice de desigualdad de género (gender_unequal). Utiliza colores para diferenciar las regiones (regionun) y agrega tooltips que muestren el nombre del país, el puntaje democrático y el índice de desigualdad de género.
Code
# Solución

# colores
col <- c("#3d98d3","#EC0B88","#5e35b1","#f9791e","#3dd378","#c6c6c6")

# Crea el tootltip
wa$tooltip_scat <- paste0("<b>", wa$name, "</b><br>Democratic Score: ", wa$dem_score14, "<br>Gender Ineq.: ", wa$gender_unequal)

p3 <- ggplot(wa, 
             aes(x = gender_unequal, y = dem_score14, color = regionun, group=regionun)) +
  geom_point_interactive(aes(tooltip = tooltip_scat, data_id = name)) +
  theme_minimal() +
  theme(panel.grid.major = element_blank(),
        legend.position = "bottom",
        plot.title=ggtext::element_markdown(size=16, face = "bold")) +
  labs(y="Democratic Score", x="Gender Inequality Index", title="Democracy and Gender Inequality")+
  scale_color_manual(values=pal$cat.awtools.ppalette.8[2:7], name="Region")


# Añade la interactividad
girafe(ggobj = p3,
       options = list(
         opts_hover(css = "fill:orange;r:5pt;"),
         opts_tooltip(css = "background-color:lightgreen; color:black; font-size:16px; padding:5px; border-radius:5px;")
       ))

Conectando todo

Hemos visto cómo crear tablas y gráficos interactivos por separado. Ahora, veamos cómo podemos combinar ambos elementos en un documento Quarto para crear una experiencia de usuario más completa.

Aquí entra el paquete patchwork, que permite combinar múltiples gráficos de ggplot2 en una sola figura. Podemos utilizar patchwork junto con ggiraph para crear un documento que incluya tanto tablas como gráficos interactivos.

Antes de seguir, echemos un vistazo al paquete patchwork. La documentación está disponible aquí.

Code
# Crea el tootltip
wa$tooltip_scat <- paste0("<b>", wa$name, "</b><br>Democratic Score: ", wa$dem_score14, "<br>HDI: ", wa$hdi)

# Crea el gráfico interactivo
p2 <- ggplot(wa, 
             aes(x = hdi, y = dem_score14, color = religoin, group=religoin)) +
  geom_point_interactive(aes(tooltip = tooltip_scat, data_id = name)) +
  theme_minimal() +
  theme(panel.grid.major = element_blank(),
        legend.position = "bottom",
        plot.title=ggtext::element_markdown(size=16, face = "bold")) +
  labs(y="Democratic Score", x="Human Development Indicator", title="Democracy and Human Development")+
  scale_color_brewer(palette="Dark2", direction = 1, name="Religion")

# colores
col <- c("#3d98d3","#EC0B88","#5e35b1","#f9791e","#3dd378","#c6c6c6")

# Crea el tootltip
wa$tooltip_scat <- paste0("<b>", wa$name, "</b><br>Democratic Score: ", wa$dem_score14, "<br>Gender Ineq.: ", wa$gender_unequal)

p3 <- ggplot(wa, 
             aes(x = gender_unequal, y = dem_score14, color = regionun, group=regionun)) +
  geom_point_interactive(aes(tooltip = tooltip_scat, data_id = name)) +
  theme_minimal() +
  theme(panel.grid.major = element_blank(),
        legend.position = "bottom",
        plot.title=ggtext::element_markdown(size=16, face = "bold")) +
  labs(y="Democratic Score", x="Gender Inequality Index", title="Democracy and Gender Inequality")+
  scale_color_manual(values=pal$cat.awtools.ppalette.8[2:7], name="Region")


library(patchwork)

# Añade la interactividad
girafe(ggobj = (p1+p2)/p3, height_svg = 10, width_svg = 10,
       options = list(
         opts_hover(css = "fill:orange;r:5pt;"),
         opts_tooltip(css = "background-color:lightgreen; color:black; font-size:16px; padding:5px; border-radius:5px;")
       ))

Un plus: Leaflet

Finalmente, veamos cómo podemos utilizar el paquete leaflet para crear mapas interactivos en R y Quarto. En este ejemplo, crearemos un mapa simple que muestre la ubicación de un punto específico con un marcador y un popup.

Code
# install.packages("leaflet")

library(leaflet)

leaflet() %>%
  addTiles() %>%  # Add default OpenStreetMap map tiles
  addMarkers(lat=40.9695, lng=-5.6767, popup="Nosotros estamos aquí")

Opciones de los bloques de código

  • eval: Esta opción controla si el código dentro del bloque se evalúa o no. Si se establece en FALSE, el código no se ejecutará, pero aún así se mostrará en el documento. Esto es útil para mostrar ejemplos de código sin ejecutarlos.

  • echo: Esta opción determina si el código dentro del bloque se muestra en el documento final. Si se establece en FALSE, el código no se mostrará, pero los resultados de su ejecución sí lo harán. Esto es útil cuando deseas mostrar solo los resultados sin revelar el código subyacente.

  • message: Esta opción controla si los mensajes generados durante la ejecución del código se muestran en el documento final. Si se establece en FALSE, los mensajes no se mostrarán. Esto es útil para evitar que mensajes innecesarios o de advertencia aparezcan en el documento.

  • warning: Similar a message, esta opción controla si las advertencias generadas durante la ejecución del código se muestran en el documento final. Si se establece en FALSE, las advertencias no se mostrarán. Esto es útil para mantener el documento limpio y libre de advertencias que no son relevantes para el lector.

  • results: Esta opción determina cómo se muestran los resultados de la ejecución del código. Puede tomar valores como asis, hold, markup, entre otros. Por ejemplo, si se establece en asis, los resultados se mostrarán tal como son generados por el código, sin ningún formato adicional. Esto es útil para mostrar resultados en formatos específicos, como tablas HTML o gráficos.

Opciones como fig.width y fig.height también son comunes para controlar el tamaño de las figuras generadas por el código. Estas opciones permiten personalizar la apariencia de los gráficos y otros elementos visuales en el documento final.

Opciones de Quarto:

  • code-fold: Esta opción permite controlar si el bloque de código está plegado (oculto) o desplegado (visible) por defecto en el documento final. Si se establece en true, el bloque de código estará plegado, lo que significa que solo se mostrará un botón para expandirlo. Esto es útil para mantener el documento limpio y permitir a los lectores expandir solo los bloques de código que les interesan.

Opciones de layout:

  • column: Esta opción permite especificar cómo se distribuye el contenido del bloque de código en diferentes columnas dentro del documento. Por ejemplo, si se establece en screen, el bloque de código ocupará todo el ancho disponible en la pantalla. Si se establece en page, el bloque de código se ajustará al ancho de la página impresa. Esta opción es útil para controlar la presentación del contenido en documentos con múltiples columnas o diseños específicos. Ver el artículo sobre Article Layout para saber las opciones completas.

  • figuras de márgenes: Quarto permite ajustar los márgenes de las figuras generadas por bloques de código. Esto se puede hacer utilizando opciones como fig.margin, que permite especificar los márgenes alrededor de una figura. Por ejemplo, se puede establecer fig.margin: 10px para agregar un margen de 10 píxeles alrededor de la figura. Esta opción es útil para mejorar la apariencia visual de las figuras y asegurarse de que no estén demasiado cerca del texto u otros elementos en el documento. También resulta válido para tablas.

  • notas en los márgenes: Quarto permite agregar notas en los márgenes de las páginas, así como las referencias bibliográficas. Eso permite un estilo de escritura más personalizado.

  • citas: Quarto soporta citas bibliográficas utilizando el formato CSL (Citation Style Language). Puedes agregar citas en el texto utilizando el formato [@clave], donde clave es la clave de la referencia en tu archivo bibliográfico (por ejemplo, un archivo .bib). Quarto generará automáticamente la lista de referencias al final del documento según el estilo especificado en el archivo CSL. Esto facilita la gestión de referencias y asegura que las citas estén correctamente formateadas según las normas académicas o de publicación. Ver más en Citations in Quarto.