Day 5 of 5
⏱ ~60 minutes
R Programming in 5 Days — Day 5

R Markdown, Shiny & Production R

R Markdown produces reproducible reports combining code, output, and prose. Shiny builds interactive web applications from R. Today covers both — the tools that turn R analysis into deliverable products.

R Markdown

An .Rmd file combines YAML header (title, author, output format), prose (Markdown), and R code chunks (```{r}...```). knit() executes all chunks and renders the result to HTML, PDF, Word, or slides. Inline code: `r round(mean(x), 2)` embeds R output in prose. Parameters make reports dynamic: users change values without editing code. R Markdown is standard for academic papers, business reports, and data science documentation.

Shiny: Interactive Web Apps

Shiny apps have two parts: ui (the layout and input/output elements) and server (the reactive logic). Input widgets: sliderInput, selectInput, textInput, dateRangeInput, fileInput. Output renderers: renderPlot, renderTable, renderText, renderUI. Reactive expressions (reactive(), observe(), eventReactive()) re-execute when inputs change. Deploy to shinyapps.io (free tier available) or self-host with Shiny Server.

Production R: Performance and Packages

R is slow for loops — vectorize everything, or use Rcpp to call C++ from R for hot loops. The future package parallelizes code across CPU cores. data.table is 10-100x faster than dplyr for large datasets (>1M rows). Package development: devtools, roxygen2 for documentation, testthat for tests. CRAN has 20,000+ packages; Bioconductor adds 2,000+ bioinformatics packages.

r
# Shiny app: interactive histogram
library(shiny)
library(ggplot2)

ui <- fluidPage(
  titlePanel('Distribution Explorer'),
  sidebarLayout(
    sidebarPanel(
      selectInput('dataset', 'Dataset',
                  choices = c('mtcars', 'iris', 'diamonds')),
      selectInput('variable', 'Variable', choices = NULL),
      sliderInput('bins', 'Bins', min=5, max=50, value=20)
    ),
    mainPanel(
      plotOutput('histogram'),
      verbatimTextOutput('stats')
    )
  )
)

server <- function(input, output, session) {
  dataset <- reactive({ get(input$dataset) })

  observeEvent(input$dataset, {
    nums <- names(Filter(is.numeric, dataset()))
    updateSelectInput(session, 'variable', choices = nums)
  })

  output$histogram <- renderPlot({
    req(input$variable)
    x <- dataset()[[input$variable]]
    ggplot(data.frame(x=x), aes(x)) +
      geom_histogram(bins=input$bins, fill='steelblue', color='white') +
      theme_minimal()
  })

  output$stats <- renderPrint({
    req(input$variable)
    summary(dataset()[[input$variable]])
  })
}

shinyApp(ui, server)
💡
Use req() inside render functions to prevent errors when inputs haven't been set yet. req(input$variable) stops the render silently if input$variable is NULL — you see a blank output instead of an error message.
📝 Day 5 Exercise
Build a Shiny Dashboard
  1. Install shiny: install.packages('shiny')
  2. Run the example app above: shinyApp(ui, server)
  3. Add a second tab showing a scatterplot of two selected numeric variables
  4. Add a downloadButton that exports the filtered data as a CSV
  5. Deploy to shinyapps.io: install.packages('rsconnect'); rsconnect::deployApp()

Day 5 Summary

  • R Markdown combines code, output, and prose in reproducible HTML/PDF/Word documents
  • Shiny ui defines layout; server defines reactive logic connecting inputs to outputs
  • req() prevents render errors when inputs are NULL during initialization
  • data.table is 10-100x faster than dplyr for datasets over 1 million rows
  • Rcpp integrates C++ into R for performance-critical loops
Challenge

Build a complete Shiny app that: loads a CSV uploaded by the user, allows column selection for X and Y axes, shows a ggplot2 scatter plot with regression line, displays summary statistics, and lets users download the plot as PDF.

Finished this lesson?