7 Cuadros de mando (dashboards)
Fecha última actualización: 2024-11-09
Instalación/carga librerías/datos utilizados
if (!require(shiny)) install.packages('shiny')
library(shiny)
if (!require(flexdashboard)) install.packages('flexdashboard')
library(flexdashboard)
Los cuadros de mando (dashboards) son aplicaciones web que presentan de forma organizada un conjunto de gráficos. Pueden ser estáticas, donde los gráficos presentan siempre los mismos datos o dinámicas, donde el usuario, a través de menús, puede elegir que datos observar en los gráficos. En este curso vamos a usar la librería shiny
para crear cuadros de mando dinámicos. Además usaremos la librería flexdashboard
como una interfaz para crear aplicaciones Shiny.
El paquete shiny
fue lanzado en 2012 por RStudio para R
. Su objetivo principal es permitir, a los usuarios de R, desarrollar aplicaciones web interactivas sin necesidad de usar JavaScript, HTML, o CSS. La principal ventaja de Shiny es que permite que las aplicaciones se actualicen automáticamente en función de la interacción del usuario, gracias a un modelo de programación reactivo, lo cual requiere la ejecución de R
en tiempo real mientras se visualiza el cuadro de mandos. Por ello, para visualizar (desplegar), un cuadro de mandos a través de un servidor web, dicho servidor debe ser configurado, usando la aplicación Shiny Server, como un servidor Shiny
que permita la ejecución en tiempo real de R. Es decir, no es tan simple como visualizar un fichero html que podemos alojar en cualquier servidor web.
flexdashboard
es una interfaz que permite crear fácilmente cuadros de mando usando un fichero R Markdown. Este paquete convierte el documento en un cuadro de mandos estructurado en filas y columnas, lo que facilita la presentación de gráficos, tablas y contenido de texto en un formato amigable y visualmente atractivo. Puede integrarse con Shiny para añadir reactividad y generar una aplicación Shiny
.
Una vez instaladas las librerías se puede crear el esqueleto de un cuadro de mando usando las instrucciones que se detallan en flexdashboard. También se puede utilizar cualquiera de los ficheros Rmd
de ejemplos de cuadros de mandos que se suministran en este curso.
Para tener una primera idea de como funciona un cuadro de mandos dinámico vamos a presentar un primer ejemplo de cuadro de mandos organizado en 2 columnas. En la primera columna ponemos un menú desplegable para que el usuario elija un continente. En la segunda columna, simplemente imprimimos la selección realizada por el usuario. Un imagen estática de la salida de este cuadro de mandos sería la siguiente (para obtener la versión dinámica copiar el código que figura debajo en un fichero Rmd y ejecutar Run document
en el menú superior (opción que reemplaza al knit
en este tipo de ficheros Rmd
)):
El código del fichero Rmd asociado a este cuadro de mandos es el siguiente:
---
title: "Ejemplo código básico de organización de un cuadro de mandos"
output: flexdashboard::flex_dashboard
runtime: shiny
---
Column {.sidebar data-width=230}
--------------------------------------------------
```{r}
shiny::selectInput(
"continente",
label = "Selección de continente",
choices = c("Africa","Asia","Europe"),
selected = "Europe"
)
```
Column
-----------------------------------------------------------------------
### Segunda columna del cuadro de mandos
```{r}
shiny::renderText({
paste("El continente elegido por el usuario es : ",input$continente)
})
```
Observamos que en la cabecera declaramos que la salida es un cuadro de mandos usando la interfaz flexdashboard
que se ejecuta usando shiny
. La primera columna es una barra lateral de ancho 230 pixels donde declaramos un menú desplegable para seleccionar el valor de una variable usando la función selectInput
. Esta función tiene 4 parámetros : El nombre de la variable (en este caso continente
), el texto que se va a poner encima del desplegable (en este caso “Selección del continente”), los valores posibles de la variable (en este caso el vector que contiene a los continentes Africa, Asia y Europe), y el valor asignado a variable por defecto (en este caso Europe). Se declara a continuación una segunda columna donde simplemente llamamos a una función shiny
que imprime el valor elegido por el usuario para la variable. Aquí hay dos cosas muy importantes a tener en cuenta: la primera es que para acceder en otras partes del código a la variable continente
del desplegable utizamos la notación input$continente
y la segunda es que solo se puede acceder al valor de input$continente
dentro de una función shiny
. En este caso, la función shiny
es renderText
. Es decir, que el chunk
:
nos hubiese generado un error dado que estamos intentando acceder a una variable dinámica del cuadro de mandos fuera de una función shiny
. Esto hay que tenerlo muy en cuenta porque es un error muy habitual al construir los cuadros de mando.
En general, la lectura y el procesado inicial de datos que no depende de los inputs
del usuario se realiza al principio en un chunk
normal. El procesado de datos que requiere el uso de los inputs
del usuario se realiza dentro de las funciones reactive
que son bloques de código que se recalculan automáticamente cada vez que cambian las entradas de las que dependen. Estas funciones almacenan su valor de salida y sólo lo recalcularán si cambian sus dependencias. Con frecuencia, una función reactive
necesita devolver (a través de un return
) varios objetos creados por ella (por ejemplo varias tablas), en ese caso, lo que haremos es devolver una lista que contiene todos los objetos. Es decir, una función reactive
de este tipo, que calcula y devuelve dos objetos data1
y data2
tendrá un código como el que sigue:
inputs.processing <- shiny::reactive({
# código que calcula data1 y data2
................
return(list(data1,data2))
})
posteriormente, cuando se necesite acceder a data1
y/o data2
dentro de una función shiny
hará lo siguiente:
FunciónShiny({
data1 <- inputs.processing()[[1]]
data2 <- inputs.processing()[[2]]
# código de la función
})
nótese que cualquier función shiny
comienza por ({
y termina con })
. Se recomienda analizar los códigos de los cuadros de mando que figuran a continuación para familiarizarse con las funciones reactive
y en general con el diseño e implementación de cuadros de mando.
7.1 Cuadro de mandos con hchart
Vamos a estudiar el ejemplo de cuadro de mando dinámico que se encuentra en Dashboard1.Rmd, cuya ejecución se visualiza a continuación (para poder interactuar con el gráfico hay que ejecutar el fichero Rmd
desde Rstudio
) :
En este cuadro de mando se presentan 4 gráficos comparativos, realizados con hchart
, de la evolución de la población en 4 países o regiones del mundo. A la izquierda aparece menús desplegables para elegir el país/región de cada gráfico y los años de inicio y final para generar el gráfico. Para generar este cuadro de mando localmente, hay que cargar el fichero Dashboard1.Rmd en Rstudio
y ejecutar run document
. Observamos que este cuadro de mando se organiza en 3 columnas: en la primera columna aparecen los menús desplegables en la segunda columna aparecen dos gráficos generados con hchart
y en la tercera columna otros 2 gráficos similares. Usando flexdashboard
este cuadro de mando se organiza de la siguiente forma :
Lectura de los datos que usa el cuadro de mandos y creación de las etiquetas que utilizarán los menús desplegables
Creación de una primera columna para poner los menús desplegables. La columna se crea usando el código:
cada menú desplegable se crea usando la función selectInput
. Esta función asocia un nombre al campo de este menú desplegable, por ejemplo country1
, en el interior de las funciones que dibujan, se accede al valor de este campo a través de input$country1
.
- Creación de una segunda columna para poner 2 gráficos apilados de la población de dos países/regiones. La columna la creamos de nuevo usando la instrucción
Cada gráfico lo creamos con la función renderHighchart
. Es decir para que aparezcan los dos gráficos el código seguiría el siguiente estilo
###
renderHighchart({
.....
código creación gráfico hchart con datos input$country1
....
})
###
renderHighchart({
.....
código creación gráfico hchart con datos input$country2
....
})
- Creación de una tercera columna de forma idéntica a la segunda, pero usando los datos de
input$country3
yinput$country4
La función renderHighchart
se usa porque es un gráfico generado con hchart
. Si fuera un gráfico generado con plotly
habría que usar la función renderPlotly
, y si fuese un gráfico de datos geográficos de Leaflet
habría que usar la función renderLeaflet
. Es decir, cada tipo de gráfico tiene asociado una función diferente en flexdashboard
. Para un gráfico estándar se utiliza la función renderPlot
.
7.2 Cuadro de mandos con Leaflet
El segundo cuadro de mando que vamos a estudiar se encuentra en el fichero Dashboard2.Rmd, cuya ejecución se visualiza a continuación:
En este caso, el cuadro de mandos tiene dos columnas. En la primera columna aparece un menú desplegable para elegir el indicador de los países que vamos a usar y aparece también una tabla con los datos del indicador en orden descendente. Las tablas en flexdashboard
, se generan usando la función renderTable
. A la derecha aparece una columna con un mapa coroplético con los valores del indicador (para interactuar con el gráfico hay que ejecutar el fichero Rmd
desde Rstudio
)
7.3 Cuadro de mandos con Plotly
El tercer cuadro de mando que vamos a estudiar se encuentra en el fichero Dashboard3.Rmd, cuya ejecución se visualiza a continuación:
Presentamos, a continuación, un cuadro de mandos dentro del ámbito del análisis de atributos que se verá en más detalle en el siguiente tema. El cuadro de mando se organiza en 3 columnas. En la primera columna se muestran algunos menús desplegables y una tabla de resultados, en la segunda columna un diagrama de puntos usando plotly
y en la tercera columna una tabla con datos.
El objetivo de este cuadro de mando es estudiar la relación entre cualquier par de indicadores sobre los países publicados por la OWID. Al primer indicador lo llamaremos \(x\) y al segundo \(y\). Por ejemplo, en la imagen anterior se muestra la comparación entre \(x=\)PIB/habitante e \(y=\)la esperanza de vida. El modelo que usaremos es la conocida regresión lineal, es decir, buscamos una relación lineal entre \(x\), \(y\), dada por
\[y=ax+b\]
donde \(a\) es la pendiente (slope) y \(b\) es el término independiente (independent). Usaremos el factor de correlación (correlation) como criterio de calidad del ajuste, cuanto más cerca de 1 esté este valor, mejor será el ajuste. Además, antes de calcular la regresión lineal damos la opción al usuario de escalar \(x\) o \(y\). Escalar \(x\) significa que sustituimos \(x\) por \(s_x(x)\), donde \(s_x()\) es la transformada utilizada, que en nuestro caso, damos como opciones \(s_x(x)=log(x)\), o \(s_x(x)=sqrt(x)\). Este tipo de escalado ya lo hemos usado en ggplot
a efectos de visualización. De la misma forma, opcionalmente, escalamos \(y\) con \(s_y(y)\), permitiendo elegir \(s_y(y)=log(y)\) o \(s_y(y)\) dada por la transformada de Box-Cox, que para \(y>0\) se define como:
\[ s_y(y)=\left\{ \begin{array} [c]{ccc}% \frac{y^{\lambda}-1}{\lambda} & si & \lambda\neq0\\ \log(y) & si & \lambda=0 \end{array} \right. \] Esta transformación es continua respecto a \(\lambda\) porque se puede demostrar fácilmente que si \(y>0\), entonces
\[Lim_{\lambda\rightarrow0}\frac{y^{\lambda}-1}{\lambda}=\log(y)\] en la práctica, el valor de \(\lambda\) se calcula automáticamente para optimizar la regresión lineal entre \(s_x(x)\) y \(s_y(y)\). Como la regresión lineal se aplica después de escalar, al final la relación entre las variables queda como
\[ s_y(y)=a\cdot s_x(x)+b \] Para cada par de indicadores elegidos, consideraremos que la mejor elección de escalados es la que maximiza la correlación. En el ejemplo que se visualiza en la imagen anterior, observamos una correlación máxima de \(0.83\) con \(s_x(x)=log(x)\) e \(s_y(y)\) la transformación de Box-Cox con \(\lambda=2\). Es decir, la relación entre \(x\) e \(y\) sería
\[ \frac{y^2-1}{2}=365.71 \cdot log(x)-707.54 \] Visualmente, en el diagrama de puntos del cuadro de mandos, cuanto mejor se ajuste la nube puntos a la recta de regresión, mejor explicará el modelo la relación entre los dos indicadores.
7.4 Opciones configuración
Existen múltiples opciones de configuración para la salida de un cuadro de mandos. Para ilustrar algunas de ellas vamos a usar el cuadro de mandos de ejemplo Dashboard4.Rmd. Este cuadro de mandos tiene un menú en la parte superior para acceder a 3 páginas. En la primera página vemos un ejemplo de renderizado de código html:
En la segunda página vemos algunos ejemplos de formato de entrada para diferentes tipos de variables:
En la tercera página se muestra una página con 2 pestañas que nos permite acceder a dos subpáginas diferentes:
7.5 Publicar un cuadro de mando
Para publicar un cuadro de mando realizado por flexdashboard
hay diversas formas (ver shiny.rstudio.com). Lo más sencillo es usar el servidor de shinyapps.io. Para ello hay que darse de alta en el citado sitio web y seguir las siguientes
instrucciones. La versión gratuita de uso del servidor permite 5 aplicaciones y 25 horas mensuales de ejecución. Otra opción más compleja, pero también gratuita, es alojar en un servidor LINUX propio el software completo.
Referencias
[BoCo64] Box, G. E., and D. R. Cox.. An analysis of transformations, Journal of the Royal Statistical Society. Series B (Methodological), 211–52, 1964.
[Shinyapps] Shinyapps
[SIAB23] Sievert, Carson, Richard Iannone, JJ Allaire, and Barbara Borges. 2023. flexdashboard: R Markdown Format for Flexible Dashboards, 2023.