Building Shiny Apps

MACS 30500 University of Chicago

November 27, 2017

What is Shiny?

  • R package from RStudio
  • Web application framework for R
  • R code \(\rightarrow\) interactive web page
  • No HTML/CSS/Javascript knowledge required
  • Great for sharing R analysis with someone scared of R

What is a Shiny app?

  • Computer running R
  • Web page
  • Computer performs calculations, sends contents to web page
  • User interacts with web page, sends updates back to computer
  • Rinse and repeat

Shiny app template

library(shiny)
ui <- fluidPage()
server <- function(input, output) {}
shinyApp(ui = ui, server = server)

Important: Do not place any code after shinyApp()

Run Shiny app in RStudio, method 1

Save file as app.R \(\rightarrow\) “Run” button turns to “Run App”

Good for creating Shiny apps quickly, all code in one file

Run Shiny app in RStudio, method 2

Save UI as ui.R and server as server.R in same directory

Good for complex Shiny apps, separates view vs logic

If using this method, do not include a call to shinyApp(...)

Run Shiny app in RStudio, method 3

File > New File > Shiny Web App…

Generates the template for you

Stop Shiny app in RStudio

Press “Esc” or click the Stop icon

Work through the tutorial until the end of Section 4

Add elements to app inside fluidPage()

library(shiny)
ui <- fluidPage("Hello CFSS")
server <- function(input, output) {}
shinyApp(ui = ui, server = server)

Add elements to app inside fluidPage()

fluidPage(
    h1("My Shiny app"),
    "Hello CFSS"
)

Add HTML to fluidPage()

  • Remember the UI simply creates HTML
  • Can use any HTML tags
    • h1() = header1
    • br() = line break
    • strong() = bold text
  • Any HTML tag can be accessed using tags object
    • h1 = tags$h1(), br = tags$br()
  • Common tags can be accesed without tags

Add HTML to fluidPage()

fluidPage(
  h1("My Shiny app"),
  h3("Subtitle"),
  "Hello",
  "CFSS",
  br(),
  strong("bold text")
)

Use a layout

sidebarLayout()

fluidPage(
  titlePanel("My Shiny app"),
  sidebarLayout(
    sidebarPanel(
      "This is a side panel"
    ),
    mainPanel(
      "And this is the main stuff"
    )
  )
)

sidebarLayout()

Work through the tutorial until the end of Section 5

Inputs and outputs

  • For interactivity, app needs inputs and outputs
  • Inputs - things user can toggle/adjust
  • Output - R objects user can see, often depend on inputs

Inputs and outputs

Inputs

library(shiny)

ui <- fluidPage(
  sliderInput(
    "num", "Choose a number",
    min = 0, max = 100,
    value = 20)
)

server <- function(input, output) {}

shinyApp(ui = ui, server = server)

Inputs

sliderInput("num", "Choose a number",
            min = 0, max = 100, value = 20)
print(sliderInput("num", "Choose a number",
            min = 0, max = 100, value = 20))
## <div class="form-group shiny-input-container">
##   <label class="control-label" for="num">Choose a number</label>
##   <input class="js-range-slider" id="num" data-min="0" data-max="100" data-from="20" data-step="1" data-grid="true" data-grid-num="10" data-grid-snap="false" data-prettify-separator="," data-prettify-enabled="true" data-keyboard="true" data-keyboard-step="1" data-data-type="number"/>
## </div>

Inputs

Inputs

sliderInput("num",
            "Choose a number",
            min = 0,
            max = 0,
            value = 20)

Work through the tutorial until the end of Section 6

Outputs

  • Plots, tables, text - anything that R creates and users see
  • Initialize as empty placeholder space until object is created
Function Outputs
plotOutput() plot
tableOutput() table
uiOutput() Shiny UI element
textOutput() text

Outputs

sliderInput("num",
            "Choose a number",
            min = 0,
            max = 0,
            value = 20)

Outputs

library(shiny)

ui <- fluidPage(
  sliderInput("num", "Choose a number",
              0, 100, 20),
  plotOutput("myplot")
)

server <- function(input, output) {}

shinyApp(ui = ui, server = server)

Summary

  • Begin app with template
  • Add elements as arguments to fluidPage()
  • Create inputs with *Input() functions
  • Create outputs with *Output() functions
  • Use server to assemble inputs into outputs

Why doesn’t my app run?

Remember to:

  • Comma-separate all the elements
  • Not add comma to the last element

Work through the tutorial until the end of Section 8

Server: assemble input into outputs with 3 rules

server <- function(input, output) {
    output$myplot <- renderPlot({
        plot(rnorm(input$num))
    })
}
  1. Save objects into output$
  2. Build objects with render*()

Output() \(\rightarrow\) render*()

Output function Render function
plotOutput() renderPlot({})
tableOutput() renderTable({})
uiOutput() renderUI({})
textOutput() renderText({})

render*() functions build reactive output to display in UI

renderPlot({
  plot(rnorm(100))
})

Server: assemble input into outputs with 3 rules

server <- function(input, output) {
    output$myplot <- renderPlot({
        plot(rnorm(input$num))
      
      # in UI:sliderInput("num", ...)
    })
}
  1. Save objects into output$
  2. Build objects with render*()
  3. Access input values with input$

Work through the tutorial until the end of Section 9

Reactivity

  • Shiny uses reactive programming
  • Reactive variables
    • When value of variable x changes, anything that relies on x is re-evaluated
    • Contrast with regular R:

      x <- 5
      y <- x + 1
      x <- 10
      # y is still 6

Reactivity

  • input$num is a reactive value

    output$myplot <- renderPlot({
      plot(rnorm(input$num))
    })
  • output$myplot depends on input$num
    • input$num changes \(\rightarrow\) output$myplot reacts
  • All inputs are automatically reactive, so if you use any input inside a render* function, the output will re-render any time input changes

Reactive contexts

  • You can define your own reactive variables
  • Reactive values can only be used inside reactive contexts
  • Any render* function is a reactive context
  • Use reactive({...}) to assign a reactive variable
  • Use observe({...}) to access a reactive variable
  • Remember: reactive variable means anything that depends on it gets re-executed automatically

Reactive contexts

Assign variable
server <- function(input, output) {
    x <- input$num + 1
}
# error
server <- function(input, output) {
  x <- reactive({
    input$num + 1
  })
}
# OK

Simple Shiny app using basic reactivity

library(shiny)
ui <- fluidPage(
  sliderInput("num", "Choose a number",
              0, 100, 20),
  plotOutput("myplot")
)

server <- function(input, output) {
  output$myplot <- renderPlot({
    plot(seq(input$num))
  })
  x <- reactive({
    input$num + 1
  })
  observe({
    print(x())
  })
}

shinyApp(ui = ui, server = server)

Work through the tutorial until the end of Section 10

Using buttons in the UI

  • Different from other inputs: you usually don’t care about the “value” of the button, you care when it’s clicked

    ui <- fluidPage(
      actionButton("btn", "Click me")
    )
    server <- function(input, output, session) {
      observe({
        cat(input$btn)
      })
    }
    shinyApp(ui = ui, server = server) 

Work through the tutorial until the end of Section 12

Share your app: shinyapps.io

  • Go to http://www.shinyapps.io/ and make an account
  • Make sure all your app files are in an isolated folder
  • Click “Publish Application” in RStudio
    • You might be asked to install a couple packages
    • Follow instructions from RStudio

Work through the tutorial until the end of Section 13

Acknowledgments