Introducción a Shiny

Introducción

Shiny es un paquete de R que permite construir aplicaciones web interactivas directamente desde R. Este curso, basado en los Tutoriales Escritos de shiny disponibles en RStudio, le permitirá comenzar a construir aplicaciones Shiny de forma inmediata.

Para seguir el tutorial se deben tener instalados algunos paquetes de R. Para ello en una sesión de R y estando conectado a internet ejecute:

install.packages(c("shiny", "maps", "mapproj", "quantmod", "ggplot2"))

Ejemplos

El paquete Shiny tiene once ejemplos incorporados que demuestran como funciona.

El primer y más sencillo de los ejemplos es Hello Shiny, el cual grafica un histograma del conjunto de datos de R faithful con un número de intervalos configurable. El usuario puede cambiar el número de intervalos con una barra deslizante y la aplicación inmediatamente responderá a la entrada. Se usará esta aplicación para explorar la estructura de una aplicación Shiny y para crear nuevas aplicaciones.

Para ejecutar Hello Shiny, escriba:

library(shiny)
runExample("01_hello")

Estructura de una aplicación Shiny

Las aplicaciones Shiny se escriben en un script simple con nombre app.R, el cual está dentro de una carpeta, digamos app-dir y la aplicación se puede ejecutar con runApp("app-dir").

El script app.R tiene tres componentes:

  • Un objeto de interfaz de usuario: ui
  • Una función de servidor: server
  • Una llamada a la función shinyApp.

El objeto ui controla el diseño y la apariencia de la aplicación, mientras que la función server contiene las instrucciones que el computador necesita para construir la aplicación. Finalmente, la función shinyApp crea los objetos de la aplicación Shiny desde el par ui/server.

Una ventaja de las aplicaciones de archivo simple es que son fáciles de compartir. Por ejemplo, si se copia y se pega el código de Hello Shiny en la consola se iniciará la aplicación.

Observe que la función server en Hello Shiny es muy simple. El script hace algunos cálculos y luego grafica un histograma con el número de intervalos requerido.

Sin embargo, note que la mayoría del código está relacionado con el uso de la función renderPlot. El comentario sobre esta función trata de explicarla, pero puede ser confuso, este concepto se cubrirá con mayor detalle más adelante.

Se puede experimentar con la aplicación Hello Shiny, revisar su código fuente e intentar entender como funciona. Pero antes de hacer eso, note que un archivo app.R necesita cargar el paquete Shiny al inicio y llamar a la función shinyApp al final:

library(shiny)

# See above for the definitions of ui and server
ui <- ...

server <- ...

shinyApp(ui = ui, server = server)

Mientras que la aplicación Hello Shiny este activa la sesión de R estará ocupada, por lo que no se podrá ejecutar ningún comando R, ya que éste estará monitoreando la aplicación y ejecutando las reacciones de la aplicación. Para recuperar la sesión de R, presione Esc o haga clic en el icono de señal de alto (que se encuentra en la esquina superior derecha del panel de la consola en RStudio).

Ejecución de una aplicación

Toda aplicación Shiny tiene la misma estructura: un archivo app.R que contiene el objeto ui, la función server y la llamada a la función shinyApp.

Se puede crear una aplicación Shiny creando una nueva carpeta y guardando un archivo app.R en ella. Se recomienda que cada aplicación este alojada dentro de una única carpeta propia.

Se puede ejecutar una aplicación Shiny usando el nombre de la carpeta como parámetro de la función runApp. Por ejemplo, si una aplicación Shiny está en una carpeta llamada my_app, se ejecuta el siguiente código:

library(shiny)
runApp("my_app")

El primer argumento de runApp es la ruta desde el directorio de trabajo a la carpeta de la aplicación.

Ejercicio 1

Cree una nueva carpeta llamada App-1 en el directorio de trabajo. Luego, copie y pegue el código de Hello Shiny en un archivo app.R dentro de la carpeta creada.

Inicie la aplicación ejecutando:

runApp("App-1")

cuyo resultado es App-1.

Luego, haga clic en Esc y realice algunos cambios en su aplicación:

  1. Cambie el título de “Hello Shiny!” A “Hello World!”.

  2. Establezca el valor mínimo de la barra deslizante en 5.

  3. Cambie el color del borde de las barras del histograma de "white" a "orange".

Cuando termine, inicie su aplicación nuevamente. El resultado del ejercicio es App-1-final.

Por defecto, las aplicaciones Shiny se muestran en modo “normal”, como la aplicación anterior. Hello Shiny y los otros ejemplos integrados se muestran en modo “showcase”, que muestra el script app.R junto con la aplicación.

Si se desea mostrar una aplicación en modo “showcase”, se puede ejecutar:

runApp("App-1", display.mode = "showcase")

Relanzar aplicaciones

Para relanzar una aplicación Shiny:

  • Ejecute runApp("App-1"), o
  • Abra el script app.R en el editor de RStudio. RStudio reconocerá el script Shiny y proporcionará un botón Run App (en la parte superior derecha del editor). Haga clic en este botón para iniciar su aplicación o use el método abreviado de teclado: Ctrl + Mayús + Entrar (Comando + Mayús + Entrar en sistemas Mac).

Resumen

Para crear su propia aplicación Shiny:

  • Cree una carpeta llamada myapp para su aplicación.
  • Guarde el script app.R dentro de la carpeta.
  • Ejecute la aplicación con runApp o usando los métodos abreviados de teclado de RStudio.
  • Salga de la aplicación Shiny mediante la tecla Esc.

Material complementario

Se pueden crear aplicaciones Shiny copiando y modificando otras aplicaciones Shiny existentes. La galería de Shiny proporciona algunos buenos ejemplos o se pueden usar los once ejemplos incorporados que se muestran a continuación.

runExample("01_hello")  # a histogram
runExample("02_text")  # tables and data frames
runExample("03_reactivity")  # a reactive expression
runExample("04_mpg")  # global variables
runExample("05_sliders")  # slider bars
runExample("06_tabsets")  # tabbed panels
runExample("07_widgets")  # help text and submit buttons
runExample("08_html")  # Shiny app built from HTML
runExample("09_upload")  # file upload wizard
runExample("10_download")  # file download wizard
runExample("11_timer")  # an automated timer

Cada uno demuestra una característica de Shiny y se abren en el modo “showcase”, esto es, mostrando el código app.R.

Interfaz de usuario ui

Construcción de una ui

Esta sección muestra cómo crear una interfaz de usuario para su aplicación.

Se usará una de las aplicaciones usadas en la sección anterior. Abra el archivo app.R y edítelo para que coincida con:

library(shiny)

# Define UI ----
ui <- fluidPage() ui <- fluidPage()

# Define server logic ----
server <- function(input, output) {

}

# Run the app ----
shinyApp(ui = ui, server = server)

Este es el mínimo de código necesario para crear una aplicación Shiny, cuyo resultado es minimal.

Diseño

Shiny usa la función fluidPage para crear una pantalla que se ajusta automáticamente a las dimensiones de la ventana del navegador. El diseño de la interfaz de usuario consiste en colocar elementos en la función fluidPage.

Por ejemplo, la función ui que se muestra a continuación crea una interfaz de usuario que tiene un panel de título y un diseño de barra lateral, que incluye un panel de barra lateral y un panel principal.

ui <- fluidPage(
  titlePanel("title panel"),

  sidebarLayout(
    sidebarPanel("sidebar panel"),
    mainPanel("main panel")
  )
)

cuyo resultado es ej1.

Los dos elementos más populares que se adicionan a fluidPage son titlePanel y sidebarLayout, creando una aplicación Shiny con una barra lateral.

sidebarLayout tiene dos argumentos output:

  • La función sidebarPanel.
  • La función mainPanel.

Estas funciones colocan contenido en el panel de la barra lateral o en el panel principal. El panel de la barra lateral aparecerá por defecto en el lado izquierdo de la aplicación. Se puede mover hacia el lado derecho dando el argumento opcional position = "right" en sidebarLayout.

ui <- fluidPage(
  titlePanel("title panel"),

  sidebarLayout(position = "right",
                sidebarPanel("sidebar panel"),
                mainPanel("main panel")
  )
)

cuyo resultado es ej2.

titlePanel y sidebarLayout crean un diseño básico para la aplicación Shiny, pero también se pueden crear diseños más avanzados.

Se puede usar navbarPage para proporcionarle a la aplicación una interfaz de usuario de varias páginas que incluya una barra de navegación. También se puede usar fluidRow y column para crear un diseño desde un sistema de cuadrícula.

Si desea obtener más información sobre estas opciones avanzadas, lea la Guía de diseño de aplicaciones Shiny. En este curso se usará sidebarLayout.

Se puede agregar contenido a la aplicación Shiny simplemente colocándolo dentro de una función *Panel. Por ejemplo, la aplicación ej2 muestra una cadena de caracteres en cada uno de sus paneles.

Contenido HTML

Para agregar contenido más avanzado, se usan las funciones etiqueta HTML de Shiny. Estas funciones son paralelas a las funciones etiqueta HTML5 comunes. Veamos algunas de ellas.

shiny function HTML5 equivalent creates
p <p> A paragraph of text
h1 <h1> A first level header
h2 <h2> A second level header
h3 <h3> A third level header
h4 <h4> A fourth level header
h5 <h5> A fifth level header
h6 <h6> A sixth level header

shiny function HTML5 equivalent creates
a <a> A hyper link
br <br> A line break (e.g. a blank line)
div <div> A division of text with a uniform style
span <span> An in-line division of text with a uniform style
pre <pre> Text ‘as is’ in a fixed width font
code <code> A formatted block of code
img <img> An image
strong <strong> Bold text
em <em> Italicized text
HTML Directly passes a character string as HTML code

Encabezados

Para crear un elemento de encabezado:

  • Seleccionar una función de encabezado (por ejemplo, h1 o h5)
  • Asignar el texto que desea ver en el encabezado

Por ejemplo, puede crear un encabezado de primer nivel que diga “My title” con h1("My title").

Para colocar el comando en la aplicación:

  • Coloque h1("My title") como argumento en titlePanel, sidebarPanel o mainPanel.

El texto aparecerá en el panel correspondiente de la aplicación.

Se pueden colocar varios elementos en el mismo panel si los separa con una coma. Por ejemplo, el código que se muestra a continuación utiliza los seis niveles de encabezados.

ui <- fluidPage(titlePanel("My Shiny App"), sidebarLayout(sidebarPanel(),
    mainPanel(h1("First level title"), h2("Second level title"),
        h3("Third level title"), h4("Fourth level title"), h5("Fifth level title"),
        h6("Sixth level title"))))

cuyo resultado es ej3.

Se pueden crear efectos en las etiquetas HTML, por ejemplo, si se quiere centrar un título se puede usar el argumento align = "center" en el correspondiente encabezado, digamos h1(“First level title”, align = “center”).

En general, se puee usar cualquier atributo de etiqueta HTML como argumento en una función de etiqueta Shiny. Si no está familiarizado con los atributos de etiqueta HTML, puede consultarlos en w3schools. A continuación se muestra un código para el objeto ui inspirado en Star Wars:

ui <- fluidPage(titlePanel("My Star Wars App"), sidebarLayout(sidebarPanel(),
    mainPanel(h6("Episode IV", align = "center"), h6("A NEW HOPE",
        align = "center"), h5("It is a period of civil war.",
        align = "center"), h4("Rebel spaceships, striking", align = "center"),
        h3("from a hidden base, have won", align = "center"),
        h2("their first victory against the", align = "center"),
        h1("evil Galactic Empire.", align = "center"))))

cuyo resultado es ej4.

Texto con formato

Shiny ofrece muchas funciones etiqueta para formatear texto. Para ilustrar esto, pegue el siguiente objeto ui en su archivo app.R. El resultado es ej5.

ui <- fluidPage(titlePanel("My Shiny App"), sidebarLayout(sidebarPanel(),
    mainPanel(p("p creates a paragraph of text."), p("A new p() command starts a new 
      paragraph. Supply a style attribute to change the entire paragraph format.",
        style = "font-family: 'times'; font-si16pt"), strong("strong() makes bold 
             text."),
        em("em() creates italicized text."), br(), code("code displays your text 
           similar to computer code"),
        div("div creates segments of text with a similar style. This division of 
      text is all blue because I passed the argument 'style = color:blue' to div",
            style = "color:blue"), br(), p("span does the same thing as div, but it
        works with",
            span("groups of words", style = "color:blue"), "that appear inside a 
        paragraph."))))

Imágenes

Las imágenes pueden mejorar la apariencia de una aplicación y ayudar a los usuarios a comprender el contenido. Shiny usa la función img para colocar archivos de imagen en su aplicación.

Para insertar una imagen, use la función img dando como argumento src el nombre del archivo de imagen, por ejemplo, img(src = "my_image.png").

También se pueden incluir otros parámetros compatibles con HTML, tales como height y width, cuyos valores se dan en píxeles. Por ejemplo:

img(src = "my_image.png", height = 72, width = 72)

La función img busca el archivo de imagen en una carpeta de nombre www en el mismo directorio que el archivo app.R.

Ejemplo:

  • Descargue la imagen R_day,
  • Guárdela en una carpeta www en el directorio de la aplicación, y
  • Modifique el archivo app.R para que incluya el siguiente objeto ui:
ui <- fluidPage(titlePanel("My Shiny App"), sidebarLayout(sidebarPanel(),
    mainPanel(img(src = "rstudio.png", height = 140, width = 140))))

El resultado es ej6.

Para obtener mayor información sobre las funciones etiquetas adicionales consulte Personalice su IU con HTML y Glosario de etiquetas HTML de Shiny.

Resumen

Con las habilidades presentadas, puede:

  • Crear una interfaz de usuario con fluidPage, titlePanel y sidebarLayout.
  • Crear un elemento HTML con una de las funciones etiqueta de Shiny.
  • Establecer atributos de etiqueta HTML en los argumentos de cada función etiqueta.
  • Agregar un elemento a su aplicación colocándola en titlePanel, sidebarPanel o mainPanel.
  • Agregar múltiples elementos a cada panel separándolos con coma.
  • Agregar imágenes a la carpeta www dentro del directorio de la aplicación Shiny y luego llamando a la función img.

Agregar widgets de control

¿Qué es un widget?

Es un elemento web con el que un usuario pueden interactuar, proporcionándole una forma para enviar valores a la aplicación Shiny. Cuando el usuario cambia un widget, su valor también lo hace.

Widgets de control

Shiny viene con una familia de widgets incorporados, cada uno creado con una función R. Por ejemplo, Shiny proporciona una función llamada actionButton que crea un Botón de acción y una función llamada sliderInput que crea una barra deslizante.

Los widgets Shiny estándar son:

Función Widget
actionButton Botón de acción
checkboxGroupInput Un grupo de casillas de verificación
checkboxInput Una sola casilla de verificación

Función Widget
dateInput Un calendario para selección de una fecha
dateRangeInput Un par de calendarios para seleccionar un rango de fechas
fileInput Un asistente de control para la carga de archivos
helpText Texto de ayuda que se puede agregar a un formulario de entrada
numericInput Un campo para ingresar números
radioButtons Un conjunto de botones para selección múltiple de única respuesta
selectInput Un cuadro con opciones para seleccionar
sliderInput Una barra deslizante
submitButton Un botón de enviar
textInput Un campo para ingresar texto

Agregar widgets

Se hace de la misma manera que se agregaron otros tipos de contenido HTML. Para agregar un widget a la aplicación, coloque una función widget en sidebarPanel o mainPanel dentro del objeto ui.

Cada función widget requiere varios argumentos. Los primeros dos argumentos para cada widget son:

  • Un nombre para el widget: el usuario no verá este nombre, pero puede usarlo para acceder al valor del widget. El nombre debe ser una cadena de caracteres.
  • Una etiqueta: esta etiqueta aparecerá con el widget en la aplicación. Debe ser una cadena de caracteres, pero puede ser una cadena vacía "".

Por ejemplo, para crear un botón de acción cuyo nombre es “action” y su etiqueta es “Action” se usa el código: actionButton("action", label = "Action")

Los argumentos restantes varían de un widget a otro. Éstos pueden ser valores iniciales, rangos o incrementos. Se pueden consultar los argumentos de un widget usando el comando de ayuda ?selectInput.

La aplicación widgets muestra los diferentes widgets disponibles.

Una buena manera de tener una idea del funcionamiento de cada widget es experimentar cambiando los valores de las funciones widget y observar los efectos.

Para mayores detalles sobre el diseño de esta aplicación Shiny, puede consultar la Guía de diseño de la aplicación.

Resumen

  • Shiny proporciona una familia de funciones para crear estos widgets.
  • Cada función requiere un nombre y una etiqueta.
  • Algunos widgets necesitan argumentos adicionales para funcionar.
  • Para agregar widgets a una aplicación se procede igual que para agregar contenido HTML.

Material complementario

La Galería de Widgets de Shiny proporciona plantillas en donde se muestra cada uno de los widgets de Shiny y cómo cambian los valores de éstos en respuesta a la entrada.

Seleccione el widget que desee y haga clic en el botón “See code” debajo del widget. La galería lo llevará a una aplicación de ejemplo que describe el widget. Para usarlo, copie y pegue el código desde el archivo de ejemplo en su archivo app.R.

En la siguiente sección, aprenderá cómo conectar widgets con una salida reactiva, que son objetos que se actualizan cada vez que el usuario cambia un widget.

Salida reactiva

Mostrar salida reactiva

Esta sección muestra cómo construir una salida reactiva para ser mostrada en una aplicación Shiny. Una salida reactiva responde automáticamente cuando un usuario cambia el valor de un widget.

Proceso de dos pasos

Se pueden crear resultados reactivos en un proceso de dos pasos.

  • Agregar un objeto R a la interfaz de usuario.
  • Indicar a Shiny cómo construir el objeto en la función server. El objeto será reactivo si el código que lo construye usa el valor de un widget.

Paso 1: Agregar un objeto R a la IU

Shiny proporciona una familia de funciones que convierten los objetos R en salida para la interfaz de usuario. Cada función crea un tipo específico de salida.

Función Output Crea
dataTableOutput Tabla de datos
htmlOutput HTML sin formato
imageOutput Imagen
plotOutput Gráfico
tableOutput Tabla
textOutput Texto
uiOutput HTML sin formato
verbatimTextOutput Texto

Se pueden agregar resultados a la ui de la misma manera que se agregaron elementos HTML y widgets, esto es, dentro de sidebarPanel o mainPanel.

Por ejemplo, el siguiente código usa textOutput para agregar texto reactivo al panel principal de la aplicación.

ui <- fluidPage(
  titlePanel("censusVis"),
  
  sidebarLayout(
    sidebarPanel(
      helpText("Create demographic maps with information from the 2010 US Census."),
      
      selectInput("var", label = "Choose a variable to display",
                  choices = c("Percent White", "Percent Black",
                              "Percent Hispanic", "Percent Asian"),
                  selected = "Percent White"),
      
      sliderInput("range", label = "Range of interest:",
                  min = 0, max = 100, value = c(0, 100))
    ),
    
    mainPanel(
      textOutput("selected_var")
    )
  )
)

Paso 2: Proporcionar el código R para construir el objeto.

Esto se debe hacer en la función server, la cual crea un objeto tipo lista de nombre output que contiene todo el código necesario para actualizar los objetos R de la aplicación.

Cada objeto R necesita tener su propia entrada en la lista, cuyo nombre debe coincidir con el elemento reactivo que se creó en la ui.

En la siguiente función server, el objeto output$selected_var coincide con textOutput("selected_var") en la iu.

server <- function(input, output) {

    output$selected_var <- renderText({
        "You have selected this"
    })

}

Una aplicación con el ui y server antes definidos se muestra en census-app.

Cada entrada en el objeto output debe ser el resultado de una función render* de Shiny, la cual captura y procesa una expresión R. Se debe usar la función render* que corresponde al tipo de objeto reactivo que se está creando.

Función render crea
renderDataTable Tabla de datos
RenderImage Imágenes (guardadas como un enlace a un archivo fuente)
renderPlot Gráfica
renderPrint Cualquier salida impresa
renderTable Marco de datos, matriz u otras estructuras similares a tablas
renderText Cadenas de caracteres
renderUI Un objeto etiqueta de Shiny o HTML


Cada función render* tiene un solo argumento: una expresión R entre llaves, {}, que puede ser una simple línea de texto, o muchas líneas de código.

La expresión R es un conjunto de instrucciones que se guardan en Shiny y se ejecutan la primera vez que se inicie la aplicación, y se vuelven a ejecutar cada vez que se necesite actualizar el objeto.

Tal expresión debe devolver el objeto pensado (un texto, un gráfico, una tabla, etc.). Si esto no ocurre o si se devuelve un tipo de objeto incorrecto, se genera un error.

Uso de valores de un widget

Al ejecutar la aplicación census-app, se muestra el texto “You have selected this” en el panel principal, que no es reactivo. Para que lo sea se debe usar un valor de un widget cuando se construye el texto.

Note que la función server menciona dos argumentos, input y output. Se sabe que output es un objeto tipo lista que almacena las instrucciones para construir los objetos R de la aplicación. El objeto input también es un objeto tipo lista que almacena los valores actuales de los widgets de la aplicación.

En la aplicación census-app se tienen dos widgets en la ui, var y range, cuyos valores se guardan en el objeto input como input$var e input$range. Como el control deslizante tiene dos valores (un mínimo y un máximo), el objeto input$range contendrá un vector de longitud dos.

Un objeto automáticamente se hace reactivo si usa un valor de un objeto input. Por ejemplo, la siguiente función server crea un texto reactivo, ya que usa el valor del widget del cuadro de selección.

server <- function(input, output) {

    output$selected_var <- renderText({
        paste("You have selected", input$var)
    })

}

cuyo resultado es census-app2.

Shiny monitorea que salidas dependen de cuales widgets. Cuando un usuario cambia un widget, Shiny reconstruirá todas las salidas que dependen del widget, utilizando el nuevo valor del widget a medida que avanza. Como resultado, los objetos reconstruidos estarán completamente actualizados.

Así es como se crea la reactividad con Shiny, conectando los valores de objetos input a los objetos output. Shiny se encarga de todos los demás detalles.

Ejercicio 2

Agregue una segunda línea de texto reactivo al panel principal de la aplicación Shiny, que muestre “You have chosen a range that goes from … to …”, y los “…” deben mostrar los valores mínimo (min) y máximo (max) actual del widget de barra deslizante.

No olvide que debe actualizar tanto el objeto ui como la función server.

Una solución al problema es census-app3.

Resumen

  • Usar una función *Output en la ui para colocar objetos reactivos en la aplicación Shiny.
  • Usar una función render* en el server para indicarle a Shiny cómo construir los objetos.
  • Encerrar las expresiones R con llaves, {}, en cada función render*.
  • Guardar las expresiones render* en la lista output, con una entrada para cada objeto reactivo en la aplicación.
  • Crear la reactividad al incluir un valor input en una expresión render*.

Shiny hará que los objetos sean reactivos automáticamente.

En la siguiente sección se creará una aplicación reactiva más sofisticada que se basa en scripts de R y datos externos.

Scripts de R y datos

Uso de scripts de R y datos

Esta sección muestra cómo cargar datos, scripts y paquetes de R en aplicaciones Shiny. Se ilustra esto con una aplicación sofisticada que visualiza los datos del censo de los EE.UU.

counties.rds

counties.rds es un conjunto de datos de datos demográficos para cada condado de los Estados Unidos, recopilados en el paquete de R UScensus2010, el cual se puede descargar aquí. Una vez descargado,

  • Cree una nueva carpeta data en el directorio de la aplicación census-app.
  • Mueva el archivo counties.rds a la carpeta data.

El conjunto de datos counties.rds contiene

  • El nombre de cada condado de los Estados Unidos.
  • La población total del condado.
  • El porcentaje de residentes en el condado que son blancos, negros, hispanos o asiáticos.
counties <- readRDS("census-app/data/counties.rds")
head(counties)
             name total.pop white black hispanic asian
1 alabama,autauga     54571  77.2  19.3      2.4   0.9
2 alabama,baldwin    182265  83.5  10.9      4.4   0.7
3 alabama,barbour     27457  46.8  47.8      5.1   0.4
4    alabama,bibb     22915  75.0  22.9      1.8   0.1
5  alabama,blount     57322  88.9   2.5      8.1   0.2
6 alabama,bullock     10914  21.9  71.0      7.1   0.2

helpers.R

helpers.R es un script de R que puede ayudar a hacer mapas coropléticos, que son mapas que usan colores para mostrar la variación regional de una variable. En nuestro caso, helpers.R creará percent_map, una función diseñada para mapear los datos en counties.rds. el script helpers.R se puede descargar aquí.

helpers.R usa los paquetes de R maps y mapproj.

Guarde el archivo helpers.R dentro de la carpeta census-app.

La función percent_map en helpers.R usa cinco argumentos:

Argumento Entrada
var Un vector columna del conjunto de datos counties.rds
color Cualquier cadena de caracteres entre las opciones de color en colors()
legend.title Una cadena de caracteres para usar como título de la leyenda del gráfico
max Un parámetro para controlar el rango de sombra (con valor predeterminado de 100)
min Un parámetro para controlar el rango de sombra (con valor predeterminado de 0)

Se puede usar percent_map desde la línea de comandos para graficar los datos de los condados como un mapa coroplético, de la siguiente forma:

library(maps)
library(mapproj)
source("census-app/helpers.R")
counties <- readRDS("census-app/data/counties.rds")
percent_map(counties$white, "darkgreen", "% White")

percent_map grafica los datos de los condados como un mapa coroplético, donde se gráfica el porcentaje de residentes blancos en los condados de color verde oscuro.

Carga de archivos y sus rutas

Note que para usar percent_map

  • Se ejecuta helpers.R con la función source.
  • Se carga counties.rds con la función readRDS.
  • Se cargaron los paquetes de R necesarios usando library(maps) y library(mapproj).

Para las funciones source y readRDS Shiny toma las rutas de los archivos desde el directorio del archivo app.R. Luego, para el ejemplo las instrucciones en Shiny son:

  • source("helpers.R").
  • readRDS ("data/counties.rds").
  • Los paquetes maps y mapproj se pueden cargar de la manera usual:
    • library(maps).
    • library(mapproj).

Ejecución y sus efectos

Shiny ejecuta todos los comandos si son colocados en el script app.R, y el lugar donde se colocan determina cuántas veces se ejecutan (o se vuelven a ejecutar).

  • Shiny ejecutará todo el script la primera vez que se llama runApp.
  • La función server se ejecuta una vez cada vez que un usuario visita la aplicación.
  • Las expresiones R dentro de las funciones render* se ejecutan cada vez que un usuario cambia el valor de un widget.

De manera que,

  • La carga de datos, scripts y paquetes se debe hacer al comienzo del archivo app.R por fuera de la función server.
  • Los objetos específicos de usuario se deben definir dentro del server, pero por fuera de los render*.
  • Dentro de la función render* se debe colocar el código requerido para volver a construir un objeto.
  • Colocar código innecesario dentro de una función render ralentizará la aplicación.

La aplicación de visualización del censo tiene un objeto reactivo, que es un gráfico de nombre "map", que se define en el panel principal de la ui, así:

ui <- fluidPage(
  titlePanel("censusVis"),
  
  sidebarLayout(
    sidebarPanel(
      ... # this defined like before
    ),
    
    mainPanel(plotOutput("map"))
  )
)

En la función server el gráfico se construye con la función percent_map, así:

server <- function(input, output){
  output$map <- renderPlot({
    percent_map( # some arguments )
  })
}

La función percent_map tiene cinco argumentos:

  • Los tres primeros argumentos: var, color y legend.title, dependen del valor del widget del cuadro de selección.
  • Los dos argumentos restantes: max y min, deberían ser los valores máximo y mínimo del widget de barra deslizante.

La siguiente función server muestra una forma de elaborar los argumentos reactivos para percent_map.

server <- function(input, output) {
  output$map <- renderPlot({
    data <- switch(input$var, 
                   "Percent White" = counties$white,
                   "Percent Black" = counties$black,
                   "Percent Hispanic" = counties$hispanic,
                   "Percent Asian" = counties$asian)
    
    percent_map(var = data, color = ?, legend.title = ?, max = ?, min = ?)
  })
}

La función switch de R puede transformar la salida de un widget de cuadro de selección a lo que se desee. Observe que el código está incompleto, ya que no da valores de color, legend.title, max o min.

Ejercicio 3

  1. Abra el archivo app.R de la aplicación census-app4 y agregue los comandos source("helpers.R"), counties <- readRDS("data/counties.rds"), library(maps) y library(mapproj).

    Asegúrese de colocar los comandos en una ubicación eficiente.

  2. Complete el código para crear una aplicación de visualización del censo que funcione.

Se debe decidir:

  • Cómo crear los valores de los argumentos percent_map, y
  • Dónde colocar el código que crea estos argumentos.

Recuerde, se desea que los valores de argumento cambien cada vez que un usuario cambie el widget asociado.

Una solución al ejercicio es census-app-final.

Resumen

Se pueden crear aplicaciones Shiny más complejas cargando conjuntos de datos, scripts y paquetes de R. Tenga en cuenta:

  • El directorio en el que aparece app.R se convertirá en el directorio de trabajo de la aplicación Shiny.
  • Shiny ejecutará el código colocado al inicio de app.R, antes de la función server, solo una vez durante la ejecución de una aplicación.
  • Shiny ejecutará el código colocado dentro de la función server varias veces, lo que puede ralentizar la aplicación.
  • La función switch es útil para acompañar a los widgets de Shiny de opción múltiple. Use switch para cambiar los valores de un widget por expresiones R.

A medida que las aplicaciones se tornan más complejas, se pueden volver ineficientes y lentas. La siguiente sección mostrará cómo crear aplicaciones modulares y rápidas con expresiones reactivas.

Expresiones reactivas

Uso de expresiones reactivas

Esta sección muestra cómo optimizar las aplicaciones Shiny con expresiones reactivas, que permiten controlar qué partes de la aplicación se actualizan y cuando, evitando cálculos innecesarios.

Para ilustrar:

  • Cree una nueva carpeta llamada stockVis en el directorio de trabajo.

  • Descargue los siguientes archivos y colóquelos dentro del directorio stockVis: app.R y helpers.R.

    StockVis utiliza el paquete quantmod de R

  • Inicie la aplicación con:

    runApp("stockVis")

    cuyo resultado es stockVis.

La aplicación stockVis

stockVis busca los precios de acciones para un símbolo de cotización y muestra los resultados como un gráfico de líneas. La aplicación permite:

  • Seleccionar una acción para ser examinada,
  • Elegir un rango de fechas para revisar,
  • Elegir si desea graficar en el eje \(y\) los precios de las acciones o el logaritmo de los precios de las acciones, y
  • Decidir si se ajustan o no los precios por la inflación.

Note que la casilla de verificación “Adjust prices for inflation” aún no funciona. Una de las tareas en esta sección es corregir el funcionamiento de tal casilla de verificación.

Por defecto, stockVis muestra las acciones para el símbolo de cotización SPY (un índice del S&P 500 total).

Para buscar otra acción se debe ingresar un símbolo de cotización de Yahoo Finance, que se pueden consultar aquí.

Algunos símbolos comunes son GOOG (Google), AAPL (Apple) y GS (Goldman Sachs).

stockVis depende en gran medida de dos funciones del paquete quantmod:

  1. Usa getSymbols para descargar los datos financieros desde sitios web tales como Yahoo finance y el Banco de la Reserva Federal de St. Louis.
  2. Usa chartSeries para mostrar los precios en un gráfico atractivo.

stockVis también usa un script R de nombre helpers.R, que contiene una función que ajusta los precios de las acciones por la inflación.

Casillas de verificación y rangos de fechas

La aplicación stockVis utiliza algunos widgets nuevos.

  • Un selector de rango de fechas, creado con dateRangeInput, y
  • Un par de casillas de verificación hechas con checkboxInput.

Los widgets de casillas de verificación son muy simples, devuelven TRUE si están marcadas, y FALSE si no están marcadas.

Las casillas de verificación tienen nombre log y adjust en el objeto ui, lo que significa que se puede buscar como input$log e input$adjust en la función server.

Simplificar los cálculos

La aplicación stockVis tiene un problema, cuando se da clic en “Plot y axis on the log scale”, el valor de input$log cambia y se reejecuta la expresión en renderPlot:

output$plot <- renderPlot({
    data <- getSymbols(input$symb, src = "yahoo", from = input$dates[1],
        to = input$dates[2], auto.assign = FALSE)

    chartSeries(data, theme = chartTheme("white"), type = "line",
        log.scale = input$log, TA = NULL)

})

Esto provoca que:

  1. getSymbols extrae de nuevo los datos de Yahoo Finance, y
  2. Se vuelva a hacer el gráfico con el eje correcto.

Note que para volver a dibujar el gráfico no es necesario extraer de nuevo los datos, luego esto ralentiza la aplicación y consume ancho de banda del servidor.

Expresiones reactivas

Una expresión reactiva es una expresión R que utiliza una entrada de widget y devuelve un valor. La expresión reactiva actualiza este valor cada vez que el widget original cambie.

Para crear una expresión reactiva, se usa la función reactive, la cual toma una expresión R rodeada de llaves.

Por ejemplo, una expresión reactiva que utiliza los widgets de stockVis para extraer los datos de Yahoo.

dataInput <- reactive({
    getSymbols(input$symb, src = "yahoo", from = input$dates[1],
        to = input$dates[2], auto.assign = FALSE)
})

Luego, para acceder a los datos de precios en renderPlot se usa dataInput().

output$plot <- renderPlot({
    chartSeries(dataInput(), theme = chartTheme("white"), type = "line",
        log.scale = input$log, TA = NULL)
})
  • Una expresión reactiva guarda el resultado la primera vez que se ejecuta.
  • La próxima vez que se llame a una expresión reactiva, ésta verificará si el valor guardado ha quedado desactualizado (es decir, si los widgets de los que depende han cambiado).
  • Si el valor no está actualizado, la expresión reactiva lo volverá a calcular (y guardará el nuevo resultado).
  • Si el valor está actualizado, la expresión reactiva devolverá el valor guardado sin realizar ningún cálculo.

Se puede usar este comportamiento para evitar que Shiny vuelva a ejecutar código innecesariamente.

Considere cómo funcionará una expresión reactiva en la aplicación stockVis a continuación.

server <- function(input, output) {

    dataInput <- reactive({
        getSymbols(input$symb, src = "yahoo", from = input$dates[1],
            to = input$dates[2], auto.assign = FALSE)
    })

    output$plot <- renderPlot({

        chartSeries(dataInput(), theme = chartTheme("white"),
            type = "line", log.scale = input$log, TA = NULL)
    })

}
library(shiny)

El resultado es stockVis2.

Cuando se hace clic en “Plot y axis on the log scale”, input$log cambiará y renderPlot se volverá a ejecutar.

Ahora:

  1. renderPlot llamará a dataInput()
  2. dataInput verificará que los widgets dates y symb no hayan cambiado
  3. dataInput devolverá el conjunto de datos guardados de precios de acciones sin volver a extraer los datos desde Yahoo.
  4. renderPlot volverá a dibujar el gráfico con el eje correcto.

Dependencias

Suponga que el usuario cambia el símbolo de acciones en el widget symb. Esto hará que el gráfico dibujado por renderPlot esté desactualizado, pero renderPlot no usa directamente a input$symb.

Shiny reconstruye automáticamente un objeto si:

  • Un valor input en la función render* de los objetos cambia, o
  • Una expresión reactiva en la función render* de los objetos se desactualiza.

Se recomienda usar una expresión reactiva adentro de una función reactive o render*, debido a que solo estas funciones de R pueden manejar una salida reactiva.

Casilla de verificación “Adjust prices for inflation”

La función adjust en helpers.R utiliza los datos del índice de precios al consumidor para transformar los precios históricos en valores actuales.

Una solución, que no es la ideal se presenta a continuación.

server <- function(input, output) {

    dataInput <- reactive({
        getSymbols(input$symb, src = "yahoo", from = input$dates[1],
            to = input$dates[2], auto.assign = FALSE)
    })

    output$plot <- renderPlot({
        data <- dataInput()
        if (input$adjust)
            data <- adjust(dataInput())

        chartSeries(data, theme = chartTheme("white"), type = "line ",
            log.scale = input$log, TA = NULL)
    })
}

El resultado es stockVis3.

Ejercicio 4

Solucione el problema anterior agregando una nueva expresión reactiva a la aplicación. La expresión reactiva debe tomar el valor de dataInput y devolver una copia ajustada (o no ajustada) de los datos.

Asegúrese de entender qué cálculos se hacen o no en la aplicación, cuando se hace clic en “Plot y axis on the log scale”.

La solución al ejercicio es stockVis-final.

Resumen

  • Una expresión reactiva toma valores input o de otras expresiones reactivas, y devuelve un nuevo valor.
  • Las expresiones reactivas guardan los resultados, y solo los vuelven a calcular si la entrada ha cambiado.
  • Las expresiones reactivas se crean con reactive({ }).
  • Para usar una expresión reactiva se usa su nombre seguido de paréntesis ().
  • Solo use expresiones reactivas dentro de otras expresiones reactivas o funciones render*.

Ahora puede crear aplicaciones Shiny sofisticadas y optimizadas. La sección final de este curso muestra cómo compartir las aplicaciones con otros.

Compartir las aplicaciones

Compartir las aplicaciones

Esta sección muestra varias formas de compartir las aplicaciones Shiny, para lo cual se tienen dos opciones básicas:

  • Compartir la aplicación Shiny como un script de R. Esta es la forma más sencilla de compartir una aplicación, pero solo funciona si los usuarios tienen R en su computadora (y saben cómo usarlo). Los usuarios pueden usar estos scripts para iniciar la aplicación desde una sesión R.

  • Compartir la aplicación Shiny como una página web. Esta es definitivamente la forma más amigable de compartir una aplicación Shiny. Los usuarios pueden acceder a la aplicación a través de internet desde un navegador. La aplicación estará totalmente procesada, actualizada y lista para funcionar.

Compartir como un script de R

En este caso cualquier usuario, que tenga copia del archivo app.R y el material complementario utilizado por la aplicación (por ejemplo, carpetas www o archivos helpers.R), puede ejecutar la aplicación Shiny.

Para enviar los archivos a otro usuario, puede hacerlo por correo electrónico (tal vez en un archivo zip) o alojar los archivos en línea. El usuario puede colocar los archivos en una carpeta en el directorio de trabajo y puede iniciar la aplicación en R con los mismos comandos que se han usado en este curso.

library(shiny)
runApp("census-app")

Shiny tiene tres comandos integrados que facilitan el uso de archivos alojados en línea: runUrl, runGitHub y runGist.

runUrl

runUrl descarga y lanza una aplicación Shiny directamente desde un enlace web. Para usarlo:

  • Guarde el directorio de la aplicación Shiny como un archivo zip.
  • Aloje el archivo zip en su propio enlace en una página web. Cualquier usuario con acceso al enlace puede iniciar la aplicación desde R ejecutando:
library(Shiny)
runUrl("<the weblink>")

runGitHub

Si no tiene su propia página web para alojar los archivos, puede alojarlos de forma gratuita en www.github.com. GitHub es un sitio popular para desarrolladores R para el alojamiento de proyectos, ya que hace más que solo alojar archivos. GitHub ofrece muchas funciones para apoyar la colaboración, como rastreadores de problemas, wikis y una estrecha integración con el sistema de control de versiones git. Para usarlo, se debe registrar (es gratis) y elegir un nombre de usuario.

Para compartir una aplicación a través de GitHub, se debe crear un repositorio de proyecto, donde se debe almacenar el archivo app.R, junto con el material complementario que use la aplicación. Los usuarios pueden iniciar la aplicación ejecutando:

runGitHub("<your repository name>", "<your user name>")

runGist

Si se desea publicar archivos en línea en forma anónima, GitHub ofrece un servicio alternativo para compartir archivos en gist.github.com, donde no se necesita tener una cuenta GitHub para usar este servicio. Incluso si tiene una cuenta de GitHub, gist es una forma simple y rápida de compartir proyectos Shiny.

Para compartir una aplicación como un gist:

  • Copie y pegue el archivo app.R en la página web de gist.
  • Anote la URL que GitHub le da al gist.

Una vez hecho el gist, los usuarios pueden iniciar la aplicación con runGist("<gist number>") donde "<gist number>" es el número que aparece al final de la dirección web del Gist.

Un ejemplo de una aplicación alojada como un gist está aquí. Puede iniciar esta aplicación con:

runGist("eb3470beb1c0252bd0289cbc89bcf36f")

Compartir como una página web

Todos los métodos anteriores comparten la misma limitación, la cual es que requieren que el usuario tenga tanto R como Shiny instalados en su computadora. Sin embargo, Shiny crea la oportunidad perfecta para compartir aplicaciones con personas que no tienen R (y no tienen intención de obtenerlo).

Una aplicación Shiny resulta ser una de las herramientas de comunicación más utilizadas en el mundo, esto es, una página web. Si se aloja la aplicación en una URL propia, los usuarios pueden visitarla (y no deben preocuparse por el código que la genera).

Si se está familiarizado con el alojamiento web o se tiene acceso a un departamento de TI, el propietario puede alojar sus aplicaciones Shiny por si mismo. En el caso contrario, si se prefiere una experiencia más fácil o se necesita asistencia, RStudio le ofrece tres formas de alojar su aplicación Shiny como una página web:

  1. shinyapps.io
  2. Shiny Server
  3. RStudio Connect

Shinyapps.io

La forma más fácil de convertir una aplicación Shiny en una página web es usar shinyapps.io, el servicio de alojamiento para aplicaciones Shiny de RStudio, el cual lo deja cargar la aplicación directamente desde una sesión de R.

El propietario tiene el control total sobre la aplicación, incluyendo las herramientas de administración del servidor. Para mayor información visite shinyapps.io.

Shiny Server

Shiny Server es un programa complementario de Shiny (gratis, de código abierto y está disponible en GitHub) que crea un servidor web diseñado para alojar aplicaciones Shiny. Shiny server puede ser ejecutado en servidores Linux y puede alojar múltiples aplicaciones Shiny en varias páginas web, y puede implementar las aplicaciones desde detrás de un firewall.

Para ver instrucciones detalladas de cómo instalar y configurar un servidor Shiny, visite la Guía de Shiny server.

RStudio Connect

Si se usa Shiny en un entorno comercial, es posible que sean de interés las herramientas de servidor que vienen con la mayoría de los programas de servidor pagos, tales como:

  • Autenticación por contraseña.
  • Soporte SSL.
  • Herramientas de administrador.
  • Soporte prioritario.

En ese caso, RStudio Connect es una plataforma de publicación para el trabajo en R en un entorno comercial, donde se comparte aplicaciones Shiny, informes en R Markdown, dashboards, gráficas, notas en Jupyter y más en un lugar conveniente. Para mayor información visite RStudio Connect.

Resumen

Las aplicaciones Shiny son fáciles de compartir, ya sea a través de scripts de R, o como una aplicación web completamente funcional con su propia URL. Cada método tiene sus propias ventajas.

  • Cualquier persona puede lanzar una aplicación siempre y cuando tenga una copia de los archivos de la misma, e instalado tanto R como Shiny.
  • runUrl, runGitHub y runGist permiten compartir y recuperar archivos Shiny desde enlaces web.
  • shinyapps.io permite convertir una aplicación Shiny en una aplicación web en vivo con su propia URL.
  • Se puede usar el programa de código abierto Shiny server para crear un servidor Linux que aloje aplicaciones Shiny.
  • Si se requiere un control más estricto o se desea administrar grandes volúmenes de tráfico, se puede adquirir RStudio Connect de RStudio.

Conclusiones del curso

Conclusiones

Hemos recorrido todo el proceso de desarrollo de Shiny, de forma que podemos crear una aplicación sofisticada y reactiva, implementarla y compartirla con otros.

El siguiente paso es practicar y luego explorar las características avanzadas de Shiny.

Para ello, el Centro de desarrollo de Shiny puede ayudarlo, ya que alberga una Galería de aplicaciones inspiradoras, junto con el código que las produce. También incluye una sección de artículos para educación continua, que examinan en profundidad algunos temas de Shiny de nivel intermedio a avanzado.

Ahora que sabes lo suficiente para crear tus propias aplicaciones Shiny. ¡Mira qué puedes hacer!