R Shiny
Shiny is a package and web framework for R.
Installation
install.packages('shiny')
Usage
Project Folders and Templates
A basic Shiny app is structured as:
<top level project folder>
run.R
<Shiny application folder>
app.R
run.R should contain:
library(shiny) runApp("<Shiny application folder>")
This is the file that should be executed to launch the web server.
A template for app.R is:
library(shiny) library(bslib) # this is a layout for the entire UI # note: `page_sidebar` comes from the `bslib` package ui <- page_sidebar( # this is a title shown above the layout title = "Hello Shiny!", # this is the sidebar element expected by this layout sidebar = sidebar( # this is a widget we are putting into the sidebar element sliderInput( # this is an ID we can reference in code inputId = "bins", # this is a title shown above the widget label = "Number of bins:", min = 1, max = 50, # this is the default value value = 30 ) ), # this is the main element expected by this layout plotOutput( # this is an ID we can reference in code outputId = "distPlot" ) ) # this is the function that serves content server <- function(input, output) { # elements of the output are referenced by the IDs set above like `output$distPlot # values from input widgets are referenced by the IDs set above like `input$bins` # `renderPlot` is a reactive function watching `input$bins` for changes output$distPlot <- renderPlot({ # note: `faithful` is a builtin data frame x <- faithful$waiting bins <- seq(min(x), max(x), length.out = input$bins + 1) hist(x, breaks = bins, col = "#007bc2", border = "white", xlab = "Waiting time to next eruption (in mins)", main = "Histogram of waiting times") }) } # this is the main application loop shinyApp(ui = ui, server = server)
Alternative Layouts
A basic page is created by fluidPage().
A basic horizontal row is created by fluidRow().
Using fluidRows and columns, a simple grid layout can be created. Note that the page is divided into 12 equal units, so at most 12 columns are possible. For example:
ui <- fluidPage( fluidRow( column(width = 4, "row 1 column 1"), column(width = 4, "row 1 column 2"), column(width = 4, "row 1 column 3") ), fluidRow( column(width = 4, "row 2 column 2", offset = 4) ), fluidRow( column(width = 4, "row 3 column 1"), column(width = 4, "row 3 column 3", offset = 4) ) )
Note that any of the literal strings like "row 1 column 1" could have been widgets instead.
A sidebar layout is best acheived with sidebarLayout, sidebarPanel, and mainPanel. For example:
ui <- fluidPage( TitlePanel("Hello Shiny!"), sidebarLayout( sidebarPanel( sliderInput("obs", "Observations:", min = 0, max = 1000, value = 500) ), mainPanel( plotOutput("distPlot") ) ) )
A tabbed layout with distinct pages is best acheived with tabsetPanel and tabPanels. For example:
ui <- fluidPage( tabsetPanel( tabPanel("Step 1", "page 1"), tabPanel("Step 2", "page 2"), tabPanel("Step 3", "page 3") ) )
Note that any of the literal strings like "page 1" could have been widgets instead. The first string values in each call are the labels shown on the navigation element.
A similar layout is acheived with navbarPage; the difference is that members can be both tabPanels and navbarMenus, which contains other tabPanels. For example:
ui <- navbarPage( tabPanel("Step 1", "page 1"), tabPanel("Step 2", "page 2"), navbarMenu("Step 3", tabPanel("Step 3a", "page 3.1"), tabPanel("Step 3b", "page 3.2"), tabPanel("Step 3c", "page 3.3") ) )
navlistPanel enables a similar mode of operation, but the navigation element is a vertical table of contents instead of a bar.
ui <- fluidPage( navlistPanel( "Do this first", tabPanel("Step 1", "page 1"), "Do this next", tabPanel("Step 2", "page 2"), tabPanel("Step 3", "page 3") ) )
Widgets
Shiny includes these input widget functions:
Function |
Widget |
Example |
selectInput |
Single- and multiple-select ropdown menu |
selectInput(inputId = "state", label = "State?", choices = c("Alabama"), multiple = TRUE) |
radioButtons |
Single-select buttons |
radioButtons(inputId = "state", label = "State?", choices = c("Alabama")) |
checkboxInput |
One multiple-select button |
checkboxInput(inputId = "yesno", label = "Yes?", value = TRUE) |
checkboxGroupInput |
Several multiple-select buttons |
checkboxGroupInput(inputId = "state", label = "State?", choices = c("Alabama"), selected = c("Alaska")) |
textInput |
Text box |
textInput(inputId = "name", label = "Name?") |
textAreaInput |
Large and resizable text box |
|
passwordInput |
Text box with some privacy |
|
sliderInput |
Numeric slider (operates as a range slider if e.g. value = c(1, 2)) |
sliderInput(inputId = "age", label = "Age?", value = 18, min = 0, max = 100) |
numericInput |
Text box accepting only numbers, with incrementing/decrementing buttons |
numericInput(inputId = "age", label = "Age?", value = 18, min = 0, max = 100) |
dateInput |
Calendar picker |
dateInput(inputId = "dob", label = "When?") |
dateRangeInput |
Paired calendar pickers |
|
These input widgets are meant to be reacted to, by referencing their values from the server function like input$id.
Shiny includes these output widget functions:
Function |
Widget |
Renderer Function |
textOutput |
Text |
renderText("Text!") |
verbatimTextOutput |
Text in a notebook cell |
renderPrint("Text!") |
tableOutput |
Table |
renderTable(head(faithful) |
dataTableOutput |
Table as for a complete data frame |
renderDataTable(faithful) |
plotOutput |
Show a base R or ggplot graphic |
renderPlot(hist(faithful, breaks = 12)) |
These output widgets are meant to be written to like output$id.
Shiny also includes actionButtons. These emit events that should be hooked on using observeEvent or eventReactive.
ui <- fluidPage( actionButton(inputId = "run", label = "Run!"), actionButton(inputId = "start", label = "Start!"), plotOutput(outputId = "distPlot") ) server <- function(input, output) { output$distPlot <- renderPlot({ # because `input$run` is referenced here, the reactive function will execute anytime that button activates # note that it will also activate on page initialization input$run renderPlot(hist(faithful, breaks = 12)) }) }
Other widgets are available from packages like shinyWidgets and DT.