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.