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:

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.


CategoryRicottone

R/Shiny (last edited 2024-05-03 22:29:22 by DominicRicottone)