Lecture Lab 9

Leon Eyrich Jessen

Creating a Simple Shiny App

But… What is Shiny? …and how does it relate to a package?

What if you wanted to “share your code” with someone who don’t know how to code? 🤔

  • A package is an ordered and documented collection of functions

  • A Shiny app is an interface on top of an ordered and documented collection of functions

General Idea is to…

  • Shiny enables writing powerful interactive web apps in R, thereby:
    • Connecting non-data literate people with data
    • Automating time consuming tasks
    • Exhibiting data to relevant stakeholders
    • Generating value by facilitating extraction of insights




Seeing is believing

Hello Shiny!

# Load the Shiny library
library("shiny")

# Define the User Interface (Frontend)
ui <- fluidPage(
  titlePanel("Hello Shiny!"),
  sidebarLayout(
    sidebarPanel(
      sliderInput(inputId = "bins",
                  label = "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30)
    ),
    mainPanel(
      plotOutput(outputId = "distPlot")
    )
  )
)

# Define the Server (Backend)
server <- function(input, output) {
  output$distPlot <- renderPlot({
    x <- faithful$waiting
    bins <- seq(min(x), max(x), length.out = input$bins + 1)
    hist(x, breaks = bins, col = "#75AADB", border = "white",
         xlab = "Waiting time to next eruption (in mins)",
         main = "Histogram of waiting times")
  })
}

# Launch the shiny app
shinyApp(ui = ui, server = server)

Note, the use of $ is base dialect for the variable bins in the input-data

Hello Shiny!

# Load the Shiny library
library("shiny")

# Define the User Interface (Frontend)
ui <- fluidPage(
  titlePanel("Hello Shiny!"),
  sidebarLayout(
    sidebarPanel(
      sliderInput(inputId = "bins",
                  label = "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30)
    ),
    mainPanel(
      plotOutput(outputId = "distPlot")
    )
  )
)

# Define the Server (Backend)
server <- function(input, output) {
  output$distPlot <- renderPlot({
    x <- faithful$waiting
    bins <- seq(min(x), max(x), length.out = input$bins + 1)
    hist(x, breaks = bins, col = "#75AADB", border = "white",
         xlab = "Waiting time to next eruption (in mins)",
         main = "Histogram of waiting times")
  })
}

# Launch the shiny app
shinyApp(ui = ui, server = server)

Hello Shiny!

  • Frontend, the user interface
    • This is where the user interacts with your app
    • Chooses arguments to function parameters
    • Choices are “requests”
  • Backend, the server
    • This is where the computations are made in response to the user’s choices
    • Chosen arguments are passed to function parameters, producing an output
    • The output is the “response”

This frontend-to-backend continuous communication is key!

Hello Shiny!

  • Frontend, the user interface
ui <- fluidPage(
  titlePanel("Hello Shiny!"),
  sidebarLayout(
    sidebarPanel(
      sliderInput(inputId = "bins",
                  label = "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30)
    ),
    mainPanel(
      plotOutput(outputId = "distPlot")
    )
  )
)
  • The sliderInput has a specific inputId set to "bins"
  • Backend, the server
server <- function(input, output) {
  output$distPlot <- renderPlot({
    x <- faithful$waiting
    bins <- seq(min(x), max(x), length.out = input$bins + 1)
    hist(x, breaks = bins, col = "#75AADB", border = "white",
         xlab = "Waiting time to next eruption (in mins)",
         main = "Histogram of waiting times")
  })
}
  • inputId from the sliderInput set to "bins" exists in the variable input

Hello Shiny!

  • Frontend, the user interface
ui <- fluidPage(
  titlePanel("Hello Shiny!"),
  sidebarLayout(
    sidebarPanel(
      sliderInput(inputId = "bins",
                  label = "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30)
    ),
    mainPanel(
      plotOutput(outputId = "distPlot")
    )
  )
)
  • The plotOutput() has a specific outputId where we can name the distPlot we defined in the server()-function
  • Backend, the server
server <- function(input, output) {
  output$distPlot <- renderPlot({
    x <- faithful$waiting
    bins <- seq(min(x), max(x), length.out = input$bins + 1)
    hist(x, breaks = bins, col = "#75AADB", border = "white",
         xlab = "Waiting time to next eruption (in mins)",
         main = "Histogram of waiting times")
  })
}
  • The plot in the server-function is saved in the special variable output, which is sent back to the ui and can be used as outputId

Defining the Input

E.g. sliderInput(inputId = "bins", ...) in “Hello Shiny!”

Defining the Input

E.g. sliderInput(inputId = "bins", ...) in “Hello Shiny!”

Defining the Input

actionButton(
  inputId = "action",
  label = "Action")
submitButton(
  text = "Submit")
checkboxInput(
  inputId = "checkbox",
  label = "Choice A",
  value = TRUE)
checkboxGroupInput(
  inputId = "checkGroup",
  label = "Select all that apply",
  choices = list(
    "Choice 1" = 1,
    "Choice 2" = 2,
    "Choice 3" = 3),
  selected = 1)
dateInput(
  inputId = "date",
  label = "Select date",
  value = "2014-01-01")

Defining the Input

dateRangeInput(
  inputId = "dates",
  label = "Select dates")
fileInput(
  inputId = "file",
  label = NULL)
helpText(
  "Note: help text isn't a true",
  "widget, but it provides an easy",
  "way to add text to accompany",
  "other widgets.")
numericInput(
  inputId = "num",
  label = "Input number",
  value = 1)

Defining the Input

radioButtons(
  inputId = "radio",
  label = "Select option",
  choices = list(
    "Choice 1" = 1,
    "Choice 2" = 2,
    "Choice 3" = 3),
  selected = 1)
selectInput(
  inputId = "select",
  label = "Select option",
  choices = list(
    "Choice 1" = 1,
    "Choice 2" = 2,
    "Choice 3" = 3),
  selected = 1)
sliderInput(
  inputId = "slider1",
  label = "Set value",
  min = 0,
  max = 100,
  value = 50)
sliderInput(
  inputId = "slider2",
  label = "Set value range",
  min = 0,
  max = 100,
  value = c(25, 75))
textInput(
  inputId = "text",
  label = NULL,
  value = "Enter text...")

Defining the Output

Output function Creates
dataTableOutput DataTable
htmlOutput raw HTML
imageOutput image
plotOutput plot
tableOutput table
textOutput text
uiOutput raw HTML
verbatimTextOutput text

E.g. plotOutput(outputId = "distPlot") in “Hello Shiny!”

Reactive versus Event Driven

Reactive

The app is automatically updated, when a user chooses an option

  • Real-time Updates
  • More simple interaction
  • Improved User Experience
  • Performance Overhead
  • Works best with smaller data

Event-Driven

The app is only updated, when the user clicks a button

  • Controlled updates after all choices have been made
  • Gives an overall better performance
  • May seem old-fashioned to some users
  • Works better with larger data

Today, we will work with creating a reactive app

In essense…

Once you get your head around the syntax and functionality of the Shiny, it’s no longer about what you can build, but what you should build. Dashboards only have value, if they create value!

Summary

  • Shiny facilitates seamless creation of powerful interactive applications
  • The analysis becomes interactive
  • Provides a user interface for dynamic data interaction
  • Connects non-data literate professionals directly to the data
  • Fully customisable
  • Allow user complete free exploration
  • Or restrict to “meaningful data interaction”
  • Used in production across industries!

Once more unto the breach, dear friends, once more!

Once more unto the breach, dear friends, once more!

  • One last time in fact!

  • Break and then the very last exercises of this year’s R for Bio Data Science course!