Lesson 23 / 25
Interactive Apps with Shiny
Build a small interactive Shiny app with inputs, outputs and reactivity.
Analysis that users can explore
Shiny turns R code into interactive web applications without writing JavaScript. An app has a UI (layout, inputs such as selectInput, dateRangeInput and sliderInput, and outputs such as plotOutput and tableOutput) and a server function that computes outputs with render functions (renderPlot, renderTable, renderText). Shiny's core idea is reactivity: outputs that read input$city automatically recompute when the user changes that input. reactive() expressions cache intermediate results shared by several outputs, avoiding repeated work, and observeEvent() runs side effects such as saving data when a button is clicked. bslib provides modern Bootstrap layouts and theming, and modules break larger apps into reusable parts. Deploy apps on Posit Connect, shinyapps.io, or your own Shiny Server or Docker container. Keep heavy data preparation out of the app, precomputing summaries where possible, so the app stays responsive. Shiny is also available for Python.
A small sales explorer app
Inputs drive a shared reactive expression and two outputs.
library(shiny)
library(bslib)
library(dplyr)
library(ggplot2)
sales <- readr::read_rds("data/sales_clean.rds")
ui <- page_sidebar(
title = "Sales explorer",
sidebar = sidebar(
selectInput("city", "City", choices = sort(unique(sales$city))),
dateRangeInput("dates", "Dates", start = min(sales$order_date), end = max(sales$order_date))
),
card(plotOutput("daily")),
card(tableOutput("top_orders"))
)
server <- function(input, output, session) {
filtered <- reactive({
sales |>
filter(city == input$city,
order_date >= input$dates[1], order_date <= input$dates[2])
}) # recomputed only when inputs change
output$daily <- renderPlot({
filtered() |>
summarise(revenue = sum(amount_inr), .by = order_date) |>
ggplot(aes(order_date, revenue)) + geom_line()
})
output$top_orders <- renderTable({
filtered() |> slice_max(amount_inr, n = 5) |> select(order_id, order_date, amount_inr)
})
}
shinyApp(ui, server)A spreadsheet that recalculates
Shiny reactivity works like spreadsheet formulas: change one input cell and every dependent cell updates automatically, while cells that do not depend on it stay as they are.
Quick check: What does a reactive() expression provide in Shiny?
- A static value computed once at start-up
- A cached result that recomputes only when the inputs it reads change, and can be shared by several outputs
- A way to write JavaScript
- A database connection
Answer
A cached result that recomputes only when the inputs it reads change, and can be shared by several outputs — reactive() expressions cache derived data and update when their dependencies change.