¿Qué es un shiny app?

Shiny es un paquete de R que facilita la creación de aplicaciones web interactivas directamente desde R. Permite a quienes no son versados en diseño web construir rápidamente una página reactiva para explorar la información.

Galería de ejemplos

Veamos algunos ejemplos de la página:

https://shiny.rstudio.com/gallery/

Componentes fundamentales de un Shiny app

Un Shiny App tiene dos componentes

  • Interfaz de Usuario (UI): Contiene los widgets para recibir el input del usuario y mostrar los outputs
  • Server: Recibe los inputs del UI y con ellos genera los outputs

Un widget es un elemento web que le permite al usuario enviar un mensaje.

Ejemplo 1. Old Faithful Geyser

Abrir el archivo ejemplo_1/app.R

Comencemos con el ejemplo más básico. Cuando creamos un nuevo shiny, nos genera este ejemplo como template.

  • Primero cargamos la librería.
library(shiny)
  • Luego definimos la interfaz de usuario.

Elementos del ui:

  • fluidPage: La función con que definimos el layout general
    • titlePanel: Para definir el título
    • sidebarLayout: Definimos que el diseño de la app va a ser con una barra lateral y un panel central
      • sidebarPanel: Dentro del sidebarPanel definimos los elementos que van en la barra lateral
        • sliderInput: Definimos que el input será ingresado desde un widget de tipo slider, y sus parámetros
      • mainPanel: Dentro del mainPanel definimos los elementos que van en el panel central
        • plotOutput: con esta función indicamos que el output es un gráfico
ui <- fluidPage(
    titlePanel("Old Faithful Geyser Data"),
    sidebarLayout(
        sidebarPanel(
            sliderInput(inputId = "bins",
                        label = "Number of bins:",
                        min = 1,
                        max = 50,
                        value = 30)
        ),
        mainPanel(
           plotOutput("distPlot")
        )
    )
)

Elementos del server

  • input: Es una lista de elementos que recibimos del ui. en este caso sólo contiene bins (el inputId)
  • output: Es una lista que generamos dentro del server. En este caso definimos el elemento distPlot
  • renderPlot: Es una función reactiva, que observa cada vez que cambia el input y vuelve a generar el output. Noten que lo que hace es envolver una porción del código entre llaves.
server <- function(input, output) {

    output$distPlot <- renderPlot({
        x    <- faithful[, 2]
        bins <- seq(min(x), max(x), length.out = input$bins + 1)
        hist(x, breaks = bins, col = 'darkgray', border = 'white')
    })
}
shinyApp(ui = ui, server = server)
LS0tCnRpdGxlOiBTaGlueSBhcHBzCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCmRhdGU6ICIiCnN1YnRpdGxlOiBFeHBsaWNhY2nDs24KLS0tCgohW10oaW1nL3NoaW55X2xvZ28ucG5nKXt3aWR0aD03NTB9CgoKCiMjIyDCv1F1w6kgZXMgdW4gc2hpbnkgYXBwPwoKU2hpbnkgZXMgdW4gcGFxdWV0ZSBkZSBSIHF1ZSBmYWNpbGl0YSBsYSBjcmVhY2nDs24gZGUgYXBsaWNhY2lvbmVzIHdlYiBpbnRlcmFjdGl2YXMgZGlyZWN0YW1lbnRlIGRlc2RlIFIuIFBlcm1pdGUgYSBxdWllbmVzIG5vIHNvbiB2ZXJzYWRvcyBlbiBkaXNlw7FvIHdlYiBjb25zdHJ1aXIgcsOhcGlkYW1lbnRlIHVuYSBww6FnaW5hIHJlYWN0aXZhIHBhcmEgZXhwbG9yYXIgbGEgaW5mb3JtYWNpw7NuLgoKIyMjIEdhbGVyw61hIGRlIGVqZW1wbG9zCgpWZWFtb3MgYWxndW5vcyBlamVtcGxvcyBkZSBsYSBww6FnaW5hOgoKCiA8Zm9udCBzaXplPSI2Ij4gW2h0dHBzOi8vc2hpbnkucnN0dWRpby5jb20vZ2FsbGVyeS9dKGh0dHBzOi8vc2hpbnkucnN0dWRpby5jb20vZ2FsbGVyeS8pIDwvZm9udD4KCgojIyMgQ29tcG9uZW50ZXMgZnVuZGFtZW50YWxlcyBkZSB1biBTaGlueSBhcHAKClVuIFNoaW55IEFwcCB0aWVuZSBkb3MgY29tcG9uZW50ZXMKCi0gSW50ZXJmYXogZGUgVXN1YXJpbyAoX1VJXyk6IENvbnRpZW5lIGxvcyBfd2lkZ2V0c18gcGFyYSByZWNpYmlyIGVsIF9faW5wdXRfXyBkZWwgdXN1YXJpbyB5IG1vc3RyYXIgbG9zIF9fb3V0cHV0c19fCi0gU2VydmVyOiBSZWNpYmUgbG9zIF9faW5wdXRzX18gZGVsIFVJIHkgY29uIGVsbG9zIGdlbmVyYSBsb3MgX19vdXRwdXRzX18gICAgCgo+IFVuIHdpZGdldCBlcyB1biBlbGVtZW50byB3ZWIgcXVlIGxlIHBlcm1pdGUgYWwgdXN1YXJpbyBlbnZpYXIgdW4gbWVuc2FqZS4KCiFbXShpbWcvYmFzaWMtd2lkZ2V0cy5wbmcpe3dpZHRoPTc1MH0KCiMjIyMgRWplbXBsbyAxLiBPbGQgRmFpdGhmdWwgR2V5c2VyCgo+IEFicmlyIGVsIGFyY2hpdm8gW2VqZW1wbG9fMS9hcHAuUl0oZWplbXBsb18xL2FwcC5SKQoKQ29tZW5jZW1vcyBjb24gZWwgZWplbXBsbyBtw6FzIGLDoXNpY28uIEN1YW5kbyBjcmVhbW9zIHVuIG51ZXZvIHNoaW55LCBub3MgZ2VuZXJhIGVzdGUgZWplbXBsbyBjb21vIF90ZW1wbGF0ZV8uIAoKLSBQcmltZXJvIGNhcmdhbW9zIGxhIGxpYnJlcsOtYS4KCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9VFJVRX0KbGlicmFyeShzaGlueSkKYGBgCgoKLSBMdWVnbyBkZWZpbmltb3MgbGEgaW50ZXJmYXogZGUgdXN1YXJpby4gCgpFbGVtZW50b3MgZGVsIHVpOgoKLSBgZmx1aWRQYWdlYDogTGEgZnVuY2nDs24gY29uIHF1ZSBkZWZpbmltb3MgZWwgX2xheW91dF8gZ2VuZXJhbAogIC0gYHRpdGxlUGFuZWxgOiBQYXJhIGRlZmluaXIgZWwgdMOtdHVsbwogIC0gYHNpZGViYXJMYXlvdXRgOiBEZWZpbmltb3MgcXVlIGVsIGRpc2XDsW8gZGUgbGEgYXBwIHZhIGEgc2VyIGNvbiB1bmEgYmFycmEgbGF0ZXJhbCB5IHVuIHBhbmVsIGNlbnRyYWwKICAgIC0gYHNpZGViYXJQYW5lbGA6IERlbnRybyBkZWwgX3NpZGViYXJQYW5lbF8gZGVmaW5pbW9zIGxvcyBlbGVtZW50b3MgcXVlIHZhbiBlbiBsYSBiYXJyYSBsYXRlcmFsCiAgICAgIC0gYHNsaWRlcklucHV0YDogRGVmaW5pbW9zIHF1ZSBlbCBpbnB1dCBzZXLDoSBpbmdyZXNhZG8gZGVzZGUgdW4gd2lkZ2V0IGRlIHRpcG8gX3NsaWRlcl8sIHkgc3VzIHBhcsOhbWV0cm9zCiAgICAtIGBtYWluUGFuZWxgOiBEZW50cm8gZGVsIF9tYWluUGFuZWxfIGRlZmluaW1vcyBsb3MgZWxlbWVudG9zIHF1ZSB2YW4gZW4gZWwgcGFuZWwgY2VudHJhbAogICAgICAtIGBwbG90T3V0cHV0YDogY29uIGVzdGEgZnVuY2nDs24gaW5kaWNhbW9zIHF1ZSBlbCBvdXRwdXQgZXMgdW4gZ3LDoWZpY28KCgpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPVRSVUV9CnVpIDwtIGZsdWlkUGFnZSgKICAgIHRpdGxlUGFuZWwoIk9sZCBGYWl0aGZ1bCBHZXlzZXIgRGF0YSIpLAogICAgc2lkZWJhckxheW91dCgKICAgICAgICBzaWRlYmFyUGFuZWwoCiAgICAgICAgICAgIHNsaWRlcklucHV0KGlucHV0SWQgPSAiYmlucyIsCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gIk51bWJlciBvZiBiaW5zOiIsCiAgICAgICAgICAgICAgICAgICAgICAgIG1pbiA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgIG1heCA9IDUwLAogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IDMwKQogICAgICAgICksCiAgICAgICAgbWFpblBhbmVsKAogICAgICAgICAgIHBsb3RPdXRwdXQoImRpc3RQbG90IikKICAgICAgICApCiAgICApCikKCmBgYAoKRWxlbWVudG9zIGRlbCBzZXJ2ZXIKCi0gYGlucHV0YDogRXMgdW5hIGxpc3RhIGRlIGVsZW1lbnRvcyBxdWUgcmVjaWJpbW9zIGRlbCBfdWlfLiBlbiBlc3RlIGNhc28gc8OzbG8gY29udGllbmUgYGJpbnNgIChlbCBpbnB1dElkKQotIGBvdXRwdXRgOiBFcyB1bmEgbGlzdGEgcXVlIGdlbmVyYW1vcyBkZW50cm8gZGVsIHNlcnZlci4gRW4gZXN0ZSBjYXNvIGRlZmluaW1vcyBlbCBlbGVtZW50byBgZGlzdFBsb3RgCi0gYHJlbmRlclBsb3RgOiBFcyB1bmEgX2Z1bmNpw7NuIHJlYWN0aXZhXywgcXVlIG9ic2VydmEgY2FkYSB2ZXogcXVlIF9jYW1iaWEgZWwgaW5wdXRfIHkgdnVlbHZlIGEgZ2VuZXJhciBlbCBvdXRwdXQuIE5vdGVuIHF1ZSBsbyBxdWUgaGFjZSBlcyBlbnZvbHZlciB1bmEgcG9yY2nDs24gZGVsIGPDs2RpZ28gZW50cmUgbGxhdmVzLiAKCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9VFJVRX0Kc2VydmVyIDwtIGZ1bmN0aW9uKGlucHV0LCBvdXRwdXQpIHsKCiAgICBvdXRwdXQkZGlzdFBsb3QgPC0gcmVuZGVyUGxvdCh7CiAgICAgICAgeCAgICA8LSBmYWl0aGZ1bFssIDJdCiAgICAgICAgYmlucyA8LSBzZXEobWluKHgpLCBtYXgoeCksIGxlbmd0aC5vdXQgPSBpbnB1dCRiaW5zICsgMSkKICAgICAgICBoaXN0KHgsIGJyZWFrcyA9IGJpbnMsIGNvbCA9ICdkYXJrZ3JheScsIGJvcmRlciA9ICd3aGl0ZScpCiAgICB9KQp9CmBgYAoKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1UUlVFfQpzaGlueUFwcCh1aSA9IHVpLCBzZXJ2ZXIgPSBzZXJ2ZXIpCmBgYAoKCg==