1 Introducción

1.1 Que es ?

Es un framework de RStudio para construir aplicaciones web en R.

Características principales:

  • Desarrollado por RStudio
  • Fácil de aprender : Pensado para los usuarios de R.
  • No es necesario conocer HTML, CSS, JavaScript.
  • R completamente integrado.
  • Futuro incierto.
    • Inestable: Algunos métodos se han convertido en deprecated muy rápidamente.
    • El modelo de negocio que persigue RStudio no está claro.
  • Situación actual:
    • Versión gratis open source y Versión Pro de pago (muy cara).
    • El propio package de Shiny permite utilizar la versión gratis open souce de la IDE RStudio como servidor no dedicado y levantar las aplicaciones en local.
    • RStudio ofrecía servidores gratis en su fase de test (no abre de nuevos, pero los abiertos en su día siguen funcionando).
    • Rstudio ha abierto una fase de test para su nuevo producto de hosting para Shiny (futuro del producto incierto).

Ver


1.2 Arquitectura aplicaciones web

arquitecturawebapp


1.3 Arquitectura Shiny

folder

Implementación:

  • server.R
    • Es la parte servidor de la aplicación
  • ui.R
    • Es la parte cliente de la aplicación

Levantar la aplicación/servidor:

  • En local con RStudio en cualquier sistema operativo.
  • En un servidor linux dedicado con el Server Shiny de RStudio (Tutorial)
  • En algun servicio de hosting especializado para Shiny (ShinyApps.io)

2 Ejemplo

ui.R

library(shiny)

shinyUI(fluidPage(

  titlePanel("Ejemplo 01"),

  sidebarLayout(
    sidebarPanel(
      sliderInput("bins",
                  "Number of bins:",
                  min = 1,
                  max = 100,
                  value = 50)
    ),

    mainPanel(
      plotOutput("distPlot")
    )
  )
))

server.R

library(shiny)

x <- rchisq(100000, df = 4)

shinyServer(function(input, output) {
  output$distPlot <- renderPlot({
    hist(x, 
         breaks = seq(min(x), max(x), length.out = input$bins + 1), 
         col = 'darkgray', border = 'white')
  })
})

Link Ejemplo 01


uischema


Ejecutar en local (RStudio como servidor de aplicaciones shiny)

library(shiny)
runApp('C:/Alabern/Material/RShiny/_rugbcn/01_components/01_example01')
library(shiny)
setwd('C:/Alabern/Material/RShiny/_rugbcn')
runApp('./01_components/01_example01')
library(shiny)
setwd('C:/Alabern/Material/RShiny/_rugbcn/01_components/01_example01')
runApp('.', port=8200, display.mode = "showcase")

3 Componentes Shiny

Tipos de componentes:


3.1 Inputs

  • numericInput
  • sliderInput
  • textInput
  • selectInput
  • radioButtons
  • checkboxGroupInput
  • checkboxInput
  • dateInput
  • dateRangeInput
  • actionButton
  • submitButton
  • fileInput

Link Inputs Example

Link RStudio Widgets Gallery


3.2 Outputs

server.R ui.R
renderPlot plotOutput
renderImage imageOutput
renderText textOutput
renderPrint verbatimTextOutput, htmlOutput
renderTable tableOutput
renderDataTable dataTableOutput
renderUI uiOutput
downloadHandler downloadButton, downloadLink

Link Outputs Example

selectizeInput (relativamente nuevo):

Deprecated
server.R
reactivePlot
reactivePrint
reactiveTable
reactiveText
reactiveUI

Link search deprecated en Shiny reference


3.3 Layout

Composición principal:

  • pageWithSideBar (deprecated)
  • fluidPage
  • fixedPage

3.3.1 pageWithSideBar

library(shiny)

shinyUI(pageWithSidebar(
  
  headerPanel("Title"),
  
  sidebarPanel(
    ...  
  ),
  
  mainPanel(
    ...
    ) 
  )
))

3.3.2 fluidPage

library(shiny)

shinyUI(fluidPage(

  ...
  
))

3.3.3 fixedlayout

library(shiny)

shinyUI(fixedlayout(

  ...
  
))

fluidPage: A fluid page layout consists of rows which in turn include columns. Rows exist for the purpose of making sure their elements appear on the same line (if the browser has adequate width). Columns exist for the purpose of defining how much horizontal space within a 12-unit wide grid it’s elements should occupy. Fluid pages scale their components in realtime to fill all available browser width. Link reference

fixedlayout: A fixed page layout consists of rows which in turn include columns. Rows exist for the purpose of making sure their elements appear on the same line (if the browser has adequate width). Columns exist for the purpose of defining how much horizontal space within a 12-unit wide grid it’s elements should occupy. Fixed pages limit their width to 940 pixels on a typical display, and 724px or 1170px on smaller and larger displays respectively. Link reference


arquitecturawebapp


Comentarios:

  • El componente pageWithSidebar ya es deprecated, y el principal motivo es su rigidez en la estructura.
  • El componente fluidlayout es mucho más flexible que el pageWithSidebar.
  • El componente fixedlayout funciona igual que el fluidlayout fijando la salido a una anchura de 724, 940 o 1170 pixels según el device de visualización, siendo la de 940 la usual. Este modo puede ser útil en casos de problemas de visualización.
  • Ver el siguiente link para un artículo sobre su uso y diferencias: Link Article - Layout Guide

Link Ejemplo 01 - pageWithSidebar (deprecated)

Link Ejemplo 01 - fluidlayout

Link Ejemplo 01 - fixedlayout


Funciones:

Componente Subcomponente Link
navbarPage() tabPanel(), navbarMenu() Link reference
navbarMenu() tabPanel() Link reference
navlistPanel() tabPanel() Link reference
titlePanel() Link reference
sidebarLayout() sidebarPanel() & mainPanel() (obligatorio) Link reference
sidebarPanel() Link reference
mainPanel() Link reference
tabsetPanel() Link reference
tabPanel() Link reference


Otras funciones:

  • fluidRow()
  • column()
  • wellPanel()
  • flowLayout()
  • verticalLayout()

Link Layout guide article

Nuevas funciones Shiny 0.10:

  • flowPanel()
  • inputPanel()
  • splitLayout()

Link realease notes shiny 0.10


3.4 Tags HTML

tags (shiny package)

  • HTML(text, …)
  • tags
  • h1(…), h2(…), h3(…), h4(…), h5(…), h6(…)
  • p(…), pre(…), code(…)
  • div(…), span(…), strong(…), em(…)
  • a(…), img(…), br(…), hr(…)

(Ver ejemplos en local)

Nuevo package htmltools separado del package de shiny a partir de Shiny 0.10: Link al package htmltools


3.5 Dynamic Inputs or Dynamic UI

ui.r

  ...
  uiOutput("IDDynamicInput")
  ...

server.r

  ...
    output$IDDynamicInput = renderUI({
      if (input$tabpanels!=2) return()
      sliderInput(inputId="maxGraphMovies", label="Numero de nodos", value=maxGraphMovies, min=2, max=50, step=1)
    })
  ...
  if (!is.null(input$maxGraphMovies)) maxGraphMovies <<- input$maxGraphMovies
  ...

4 Reactive & Isolate

Herramientas para controlar el flujo de cálculo:

Otros: observe, flushReact

** Usamos funciones -Output en ui.R para colocar objectos “reactive”. ** Usamos funciones render- en server.R para que Shiny sepa como crear estos objectos “reactive”. ** Las expresiones reactivas van entre {} dentro de las funciones render-. ** Salvamos las render- expressions en el output list. ** Creamos reactividad cada vez que incluymos un input en una expression render-. ** Una “reactive expression” (reactive({})) toma inputs o valores de otra “reactive expression” y retorna nuevos valores. ** Una “reactive expression” guarda sus resultaos, y solo se recalcula si algun input se ha modificado. ** Solo podemos llamar a “reactive expression” dentro de otra “reactive expression” o dentro de funciones render-.


arquitecturawebapp


arquitecturawebapp


arquitecturawebapp


arquitecturawebapp


4.1 Reactive Expressions

fib <- function(n) ifelse(n<3, 1, fib(n-1)+fib(n-2))

shinyServer(function(input, output) {
  currentFib         <- reactive({ fib(as.numeric(input$n)) })

  output$nthValue    <- renderText({ currentFib() })
  output$nthValueInv <- renderText({ 1 / currentFib() })
})

4.2 Isolate

# Separate calls to isolate -------------------------------
x <- isolate({ input$xSlider }) + 100
y <- isolate({ input$ySlider })  * 2
z <- x/y

# Single call to isolate ----------------------------------
isolate({
  x <- input$xSlider + 100
  y <- input$ySlider * 2
  z <- x/y
})

# Single call to isolate, use return value ----------------
z <- isolate({
  x <- input$xSlider + 100
  y <- input$ySlider * 2
  x/y
})


5 Entorno de les variables

# Compartidas para todas las sessiones
varSharedA <- 1
varSharedB <- 1

shinyServer(function(input, output) {
  # Propias de cada sesion
  
  varNonShared <- 1 # Propia de la sesion
  varSharedA <<- varSharedA + 1 # Compartida entre sesiones
  varSharedB <- varSharedB + 1 # Propia de la sesion pero inicializada con la compartida entre sesiones
  
  ...
})
varA <- 1
varB <- 1
listA <- list(X=1, Y=2)
listB <- list(X=1, Y=2)

shinyServer(function(input, output) {
  # Create a local variable varA, which will be a copy of the shared variable
  # varA plus 1. This local copy of varA is not be visible in other sessions.
  varA <- varA + 1

  # Modify the shared variable varB. It will be visible in other sessions.
  varB <<- varB + 1

  # Makes a local copy of listA
  listA$X <- 5

  # Modify the shared copy of listB
  listB$X <<- 5

  # ...
})

5.1 Client Data per session variables

...

shinyServer(function(input, output, session) {
  startTime <- Sys.time()
  
  ...

  output$urlText <- renderText({
    paste(sep = "",
      "protocol: ", session$clientData$url_protocol, "\n",
      "hostname: ", session$clientData$url_hostname, "\n",
      "pathname: ", session$clientData$url_pathname, "\n",
      "port: ",     session$clientData$url_port,     "\n",
      "search: ",   session$clientData$url_search,   "\n",
      "startTime: ",  startTime,   "\n"
    )
  })
  
  ...
})

6 Interficies HTML

Passar de ui.R a www/index.html

(Ver ejemplos en local)


7 Extending Shiny

(Ver ejemplos en local)


8 Visualizaciones JavaScript

9 Share your apps


Local

library(shiny)
runApp('C:/Alabern/Material/RShiny/_rugbcn/01_components/01_example01')

URL (En formato zip)

library(shiny)
runUrl( "<the weblink>")

GitHub

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

Gist

library(shiny)
runGist("3239667")

ShinyApps.io

Setup

devtools::install_github('rstudio/shinyapps')
library(shinyapps)
Sys.setlocale(locale="English")
shinyapps::setAccountInfo(name='your_username', token='your_token', secret='your_Secret')
applications()

Start-Up

deployApp(appDir=strPath, appName="ShinyIDE")

Shut-Down

terminateApp('01_fluidlayout')

Links

Shiny Server Open Source

Shiny Server Pro


10 Documentos interactivos

10.1 Formatos soportados

R MarkDown outputs que permiten runtime shiny:

  • html_document
  • ioslides_presentation

10.2 Embedded Shiny Code

Chunk R

inputPanel(
  selectInput("n_breaks", label = "Number of bins:",
              choices = c(10, 20, 35, 50), selected = 20),
  
  sliderInput("bw_adjust", label = "Bandwidth adjustment:",
              min = 0.2, max = 2, value = 1, step = 0.2)
)

renderPlot({
  hist(faithful$eruptions, probability = TRUE, breaks = as.numeric(input$n_breaks),
       xlab = "Duration (minutes)", main = "Geyser eruption duration")
  
  dens <- density(faithful$eruptions, adjust = input$bw_adjust)
  lines(dens, col = "blue")
})

10.3 Inline Applications

Chunk R

shinyApp(
  
  ui = fluidPage(
    selectInput("region", "Region:", 
                choices = colnames(WorldPhones)),
    plotOutput("phonePlot")
  ),
  
  server = function(input, output) {
    output$phonePlot <- renderPlot({
      barplot(WorldPhones[,input$region]*1000, 
              ylab = "Number of Telephones", xlab = "Year")
    })
  },
  
  options = list(height = 500)
)

10.4 Widgets

Set up

kmeans_cluster <- function(dataset) { 
  
  require(shiny)  
  
  shinyApp(
    ui = fluidPage(responsive = FALSE,
      fluidRow(style = "padding-bottom: 20px;",
        column(4, selectInput('xcol', 'X Variable', names(dataset))),
        column(4, selectInput('ycol', 'Y Variable', names(dataset),
                              selected=names(dataset)[[2]])),
        column(4, numericInput('clusters', 'Cluster count', 3,
                               min = 1, max = 9))
      ),
      fluidRow(
        plotOutput('kmeans', height = "400px")  
      )
    ),
    
    server = function(input, output, session) {
      
      # Combine the selected variables into a new data frame
      selectedData <- reactive({
        dataset[, c(input$xcol, input$ycol)]
      })
      
      clusters <- reactive({
        kmeans(selectedData(), input$clusters)
      })
      
      output$kmeans <- renderPlot(height = 400, {
        par(mar = c(5.1, 4.1, 0, 1))
        plot(selectedData(),
             col = clusters()$cluster,
             pch = 20, cex = 3)
        points(clusters()$centers, pch = 4, cex = 4, lwd = 4)
      })
    },
    
    options = list(height = 500)
  )
}

Chunk R

library(rmdexamples)
kmeans_cluster(iris)

10.5 External Applications

Chunk R

shinyAppDir(
  system.file("examples/06_tabsets", package="shiny"),
  options=list(
    width="100%", height=700
  )
)

10.6 Método iframe

La opción existente antes para incrustar Shiny dentro de documentos html era vía iframe. Esta opción es menos limpia, pero permite separar servidor de aplicaciones shiny de la presentación.

Sin chunk

<iframe src="http://spark.rstudio.com/rocalabern/01_fluidlayout/"
 style="width: 940px; height: 600px"></iframe>

11 Alternativas a Shiny

Listado de posibilidades para crear aplicaciones web


12 Resources