# Paquetes instalados en los capítulos anteriores
install.packages("tidyverse")
install.packages("DT")
install.packages("plotly")
install.packages("sf")
install.packages("leaflet")
install.packages("leaflet.extras")
install.packages("leafem")
# Paquetes necesarios para este capítulo
install.packages("shiny")
install.packages("rsconnect")
install.packages("quarto")
15 shiny - marco de trabajo para desarrollo de aplicaciones web interactivas
15.1 Trabajo previo
15.1.1 Instalación de R, RStudio y paquetes
Los ejemplos de este capítulo se probaron con:
Y se instalaron los siguientes paquetes de R:
15.1.2 Lecturas
Quarto - Shiny. (s. f.). Recuperado 20 de noviembre de 2022, de https://quarto.org/docs/interactive/shiny/
15.2 Resumen
Shiny es un paquete de R que facilita el desarrollo de aplicaciones web interactivas. Las aplicaciones shiny se componen de una interfaz de usuario y de un servidor. En la interfaz de usuario, este puede realizar operaciones como filtros, búsquedas y ordenamientos de datos, entre otras. El servidor se encarga de procesar los datos de acuerdo con los parámetros especificados y de retornar los resultados a la interfaz de usuario.
Además de los bloques de código en R para la interfaz de usuario y el servidor, shiny proporciona bloques para compartir código y datos. También para personalizar la interfaz de usuario.
Las funciones reactivas de shiny se ejecutan cada vez que el usuario cambia los controles de la interfaz, lo que permite a las aplicaciones shiny responder dinámicamente a las entradas del usuario.
15.3 Introducción
En una aplicación interactiva, el usuario puede configurar las salidas, usualmente mediante una interfaz que le permite realizar operaciones como filtros, búsquedas y ordenamientos, entre otras. Shiny es un paquete de R que facilita el desarrollo de este tipo de aplicaciones.
Las aplicaciones shiny requieren un servidor, el cual es un proceso que puede alojarse en cualquier computador habilitado para ejecutar código en R como, por ejemplo, la estación de trabajo del programador (esta opción se usa principalmente para efectos de desarrollo y pruebas), un servidor ubicado en la red de una organización o un servidor en la nube (ej. shinyapps.io, Posit Connect, Posit Cloud).
Para ejemplos de aplicaciones shiny, puede visitar la siguiente galería.
15.4 Arquitectura
Una aplicación shiny tiene dos componentes principales:
- Interfaz de usuario: despliega controles de entrada y salida (widgets), los cuales eventualente convierte a Lenguaje de Marcado de Hipertexto (HTML).
- Widgets de entrada: campos de texto, listas de selección, botones de radio, etc.
- Widgets de salida: tablas, gráficos, mapas, etc. Muchos de estos controles están incluídos en los paquetes que generan los diferentes tipos de salidas (ej. DT, plotly, leaflet).
- Servidor: es un proceso que recibe las entradas y realiza el procesamiento necesario para generar las salidas y retornar los resultados a la interfaz de usuario.
Para más información sobre la arquitectura de aplicaciones shiny, se recomienda leer The Anatomy of a Shiny Application.
15.5 Ejemplo de aplicación básica
El siguiente documento Quarto contiene una aplicación shiny que muestra la distribución de la duración de los tiempos de espera entre erupciones del géiser “Old Faithful”, a través de un histograma. El usuario especifica la cantidad de bins del histograma a través de un widget de tipo sliderInput, luego el servidor genera el histograma con la cantidad de bins especificada y lo retorna a la interfaz de usuario para desplegarlo.
---
title: "Old Faithful"
format: html
server: shiny
---
```{r}
#| label: interfaz-usuario
# Este bloque de código dibuja la interfaz de usuario,
# tanto los controles de entrada como los de salida
# Widget de tipo "slider" para entrada de datos
sliderInput(
inputId = "cantidad_bins", # "cantidad_bins" es el identificador del widget de entrada
label = 'Cantidad de bins del histograma:',
min = 1, max = 50, value = 30
)
# Gráfico de salida, con el identificador "histograma"
plotOutput(outputId = "histograma")
```
```{r}
#| label: servidor
#| context: server
# Este bloque realiza el procesamiento en el servidor.
# Generación del gráfico de salida, el cual va a ser retornado
# por la función plotOutput() a la interfaz de usuario
$histograma <- renderPlot({
output# Vector con datos de duración de tiempos de espera entre erupciones
<- faithful[, 2]
tiempo_espera
# "Bins" del histograma que se generan con base
# en el valor especificado por el usuario en el widget de entrada
<- seq(
bins from = min(tiempo_espera),
to = max(tiempo_espera),
length.out = input$cantidad_bins + 1
)
# Histograma que se retorna a la interfaz de usuario
hist(x = tiempo_espera,
breaks = bins,
main = 'Distribución de duración de tiempos de espera entre erupciones',
xlab = "Duración de los tiempos de espera (min)",
ylab = "Frecuencia",
col = 'darkgray',
border = 'white')
})```
Es de vital importancia comprender que los dos bloques de código del ejemplo anterior se ejecutan en sesiones de R completamente separadas. Esto implica que no es posible, en principio, acceder desde el primer bloque variables definidas en el segundo, ni viceversa. Sin embargo, existen varias estrategias para compartir código, como las que se detallan en Sharing Code y que se detallan en secciones siguientes de este documento.
Una forma en la que la interfaz de usuario y el servidor pueden comunicarse, es a través de las listas input
y output
.
input
contiene la lista de widgets de entrada (listas de selección, campos de entrada de texto, botones de radio, etc.). Cada uno de estos widgets tiene uninputId
único. En el ejemplo, “cantidad_bins” es el inputId del widget tipo sliderInput. Se referencia comoinput$cantidad_bins
en el bloque del servidor.output
es una lista de componentes que se crean o modifican en el servidor (tablas, gráficos, mapas, etc). y que luego se envían a la interfaz de usuario para su visualización. Para crear o modificar un elemento deoutput
, se utiliza una funciónrender*
, y para mostrarlo en la interfaz de usuario, se utiliza una función*Output
. En el ejemplo,output$histograma
es un gráfico que se crea con la funciónrenderPlot()
en función del valor deinput$cantidad_bins
, y se muestra en la interfaz de usuario conplotOutput()
.
Nótese que hay diferencias importantes entre este documento y otros documentos Quarto:
La opción
server: shiny
: en la sección YAML, la cual le indica a Quarto que debe iniciar un servidor Shiny.La opción
context: server
: en el segundo bloque de código, la cual indica que ese bloque debe ejecutarse en el servidor.
Existen otros posibles valores de context
para los bloques de código en aplicaciones shiny, los cuales permiten compartir código y datos.
15.6 Bloques para compartir código y datos
Como puede apreciarse en el ejemplo anterior, las aplicaciones shiny pueden contener bloques de código que se ejecutan en tiempo de despliegue (rendering) de la interfaz de usuario y también bloques que se ejecutan en el servidor en respuesta a las acciones del usuario y a los cambios en los valores de entrada. Estos tipos de bloques se identifican respectivamente mediante las opciones context: render
(valor por defecto de context
) y context: server
.
Existen también otros tipos de bloques, los cuales permiten compartir código y datos.
15.6.1 context: setup
El código de este tipo de bloques se ejecuta tanto en el contexto de la interfaz de usuario como del servidor. Puede usarse para operaciones que se ejecutan al inicio de una aplicación, como la carga de paquetes.
```{r}
#| label: inicio
#| context: setup
#| message: false
# Carga de paquetes
library(tidyverse)
library(DT)
library(sf)
```
15.6.2 context: data
Se utiliza para cargar datos que deben compartirse entre todos los bloques de código. Por ejemplo:
```{r}
#| label: lectura-datos
#| context: data
# Lectura de archivo CSV
<-
felidos st_read(
dsn = "felidos.csv",
options = c(
"X_POSSIBLE_NAMES=decimalLongitude",
"Y_POSSIBLE_NAMES=decimalLatitude"
),quiet = TRUE
)```
15.7 Bloques para configurar la interfaz de usuario
Por defecto, los widgets que componen la interfaz de usuario se distribuyen automáticamente en la pantalla, usualmente de arriba hacia abajo. Las opciones panel: sidebar
y panel: fill
, entre otras, permiten personalizar la ubicación de los widgets.
Para utilizar estas opciones, es necesario especificar page-layout: custom
en la sección de YAML. Por ejemplo:
---
title: "Félidos de Costa Rica"
format:
html:
theme: cosmo
page-layout: custom
server: shiny
---
15.7.2 panel: fill
y panel: center
Estos bloques rellenan el espacio que queda disponible luego de desplegar un bloque del tipo panel: sidebar
. Los bloques panel: center
incluyen un margen horizontal alrededor del contenido. Pueden emplearse para desplegar salidas como tablas, gráficos y mapas. Por ejemplo:
```{r}
#| panel: fill
# Tabla interactiva
dataTableOutput("tabla")
```
15.7.3 Funciones reactivas
Son funciones especiales que se ejecutan cada vez que cambia uno de los datos que utiliza como entrada, como un widget de la interfaz de usuario. En el siguiente bloque de código se define una función reactiva que utiliza el valor especificado por el usuario en una lista de selección para filtrar un conjunto de datos.
```{r}
# Función reactiva para filtrar los registros de presencia de félidos
# de acuerdo con el valor de una lista de selección
<- reactive({
filtrar_felidos # Valor inicial del objeto que va a retornarse
<- felidos
felidos_filtrados
if (input$especie != "Todas") {
<-
felidos_filtrados |>
felidos_filtrados filter(species == input$especie)
}
return(felidos_filtrados)
}) ```
Las funciones reactivas permiten a las aplicaciones shiny responder dinámicamente a las entradas del usuario.
15.8 Ejercicios
Ejecute en su computadora el código de la aplicación “Old Faithful” mostrado anteriormente.
- Cree un proyecto en RStudio.
- Cree un documento Quarto.
- Copie en el nuevo documento el código de la aplicación “Old Faithful”.
- Ejecute el documento con el botón
Run Document
.
Publique la aplicación “Old Faithful” en shinyapps.io (puede consultar Quarto - Running Documents y How to Deploy R Shiny App for Free on Shinyapps.io).
- Cree una cuenta en shinyapps.io.
- Obtenga su token de autenticación de shinyapps.io en Accounts - Tokens - Show- Show secret - Copy to clipboard.
- Ejecute la aplicación en su computadora y publíquela en shinyapps.io con el botón Publish. Elija la opción shinyapps.io e ingrese el token cuando se le solicite. Debe seleccionar todos los archivos requeridos para que su aplicación funciones (archivos .qmd, archivos .html, archivos de datos, etc).
Ejecute en su computadora y luego publique en shinyapps.io la aplicación Iris K-Means Clustering.
Estudie el resto de los ejemplos en Quarto - Shiny - Examples.
Cree una aplicación shiny para el conjunto de datos de registros de presencia de félidos de Costa Rica, y publíquela en shinyapps.io, con los siguientes componentes:
- Una lista de selección de especies.
- Una tabla DT que muestre los registros de la especie seleccionada en la lista.
- Un gráfico ggplot2-plotly de barras que muestre la cantidad de registros por mes de la especie seleccionada en la lista.
- Un mapa leaflet que muestre la ubicación de los registros de la especie seleccionada en la lista.
Puede encontrar una solución parcial en https://github.com/gf0604-procesamientodatosgeograficos/2023-i-felidos-shiny.
15.9 Recursos de interés
Quarto - Running Documents. (s. f.). Recuperado 20 de noviembre de 2022, de https://quarto.org/docs/interactive/shiny/running.html
Shiny. (s. f.). Recuperado 20 de noviembre de 2022, de https://shiny.rstudio.com/
Shiny - Gallery. (s. f.). Recuperado 20 de noviembre de 2022, de https://shiny.rstudio.com/gallery/
The Anatomy of a Shiny Application | R-bloggers. (2021). Recuperado 21 de noviembre de 2022, de https://www.r-bloggers.com/2021/04/the-anatomy-of-a-shiny-application/
1littlecoder. (2020). How to Deploy R Shiny App for Free on Shinyapps.io. https://www.youtube.com/watch?v=2QstfyGX4ZU