Interactive Documents With Shiny

Biostat 203B

Author

Dr. Hua Zhou @ UCLA

Published

February 14, 2023

Display machine information for reproducibility.

sessionInfo()
R version 4.2.2 (2022-10-31)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Big Sur ... 10.16

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.2/Resources/lib/libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.2/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.10       later_1.3.0       digest_0.6.31     mime_0.12        
 [5] R6_2.5.1          lifecycle_1.0.3   xtable_1.8-4      jsonlite_1.8.4   
 [9] magrittr_2.0.3    evaluate_0.20     rlang_1.0.6       cli_3.6.0        
[13] promises_1.2.0.1  rstudioapi_0.14   ellipsis_0.3.2    rmarkdown_2.20   
[17] tools_4.2.2       htmlwidgets_1.6.1 shiny_1.7.4       httpuv_1.6.8     
[21] xfun_0.37         yaml_2.3.7        fastmap_1.1.0     compiler_4.2.2   
[25] htmltools_0.5.4   knitr_1.42       

1 Why Shiny?

2 Inputs and outputs

Recall Diamonds is a data set available from ggplot2.

library(tidyverse)
library(shiny)
diamonds
# A tibble: 53,940 × 10
   carat cut       color clarity depth table price     x     y     z
   <dbl> <ord>     <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl>
 1  0.23 Ideal     E     SI2      61.5    55   326  3.95  3.98  2.43
 2  0.21 Premium   E     SI1      59.8    61   326  3.89  3.84  2.31
 3  0.23 Good      E     VS1      56.9    65   327  4.05  4.07  2.31
 4  0.29 Premium   I     VS2      62.4    58   334  4.2   4.23  2.63
 5  0.31 Good      J     SI2      63.3    58   335  4.34  4.35  2.75
 6  0.24 Very Good J     VVS2     62.8    57   336  3.94  3.96  2.48
 7  0.24 Very Good I     VVS1     62.3    57   336  3.95  3.98  2.47
 8  0.26 Very Good H     SI1      61.9    55   337  4.07  4.11  2.53
 9  0.22 Fair      E     VS2      65.1    61   337  3.87  3.78  2.49
10  0.23 Very Good H     VS1      59.4    61   338  4     4.05  2.39
# … with 53,930 more rows

2.1 Numeric input, table output

To dynamically display the first rows:

2.2 Slider input, plot output

To dynamically tune the histogram of variable carat:


3 Building a Shiny app

Shiny app is a standalone app.

  • A Shiny app has 3 components:

    1. ui: assemble the HTML user interface for your app.

    2. server: a function with instructions on how to build and rebuild the R objects displayed in the UI.

    3. shinyApp: combines ui and server into an app.

4 Shiny app: first example

  1. MyFirstShinyApp folder. Recall the faithful data
head(faithful)
  eruptions waiting
1     3.600      79
2     1.800      54
3     3.333      74
4     2.283      62
5     4.533      85
6     2.883      55
  1. Deploy your Shiny app to shinyapps.io.

5 Shiny app: censusVis

counties <- readRDS("census-app/data/counties.rds")
head(counties)
             name total.pop white black hispanic asian
1 alabama,autauga     54571  77.2  19.3      2.4   0.9
2 alabama,baldwin    182265  83.5  10.9      4.4   0.7
3 alabama,barbour     27457  46.8  47.8      5.1   0.4
4    alabama,bibb     22915  75.0  22.9      1.8   0.1
5  alabama,blount     57322  88.9   2.5      8.1   0.2
6 alabama,bullock     10914  21.9  71.0      7.1   0.2
  • Use maps package, mapproj package and helpers.R file to plot maps:
library(maps)
library(mapproj)
source("census-app/helpers.R")
percent_map(counties$white, "darkgreen", "% White")

  • Shiny app.
  • Code for the Shiny app census-app.

  • The shinyApp function is run once, when you launch your app.

  • The server function is run once each time a user visits your app.

  • The R expressions inside render* functions are run many times. Shiny runs them once each time a user change the value of a widget.

  • Source scripts, load libraries, and read data sets at the beginning of app.R outside of the server function. Shiny will only run this code once, which is all you need to set your server up to run the R expressions contained in server.

  • Define user specific objects inside server function, but outside of any render* calls. These would be objects that you think each user will need their own personal copy of. For example, an object that records the user’s session information. This code will be run once per user.

6 Shiny app: reactive expressions

output$plot <- renderPlot({
  data <- getSymbols(input$symb, src = "yahoo",
                     from = input$dates[1],
                     to = input$dates[2],
                     auto.assign = FALSE)
  
  chartSeries(data, theme = chartTheme("white"),
              type = "line", log.scale = input$log, TA = NULL)
})

Each time renderPlot re-runs:
1. it re-fetches the data from Yahoo Finance with getSymbols, and 2. it re-draws the chart with the correct axis.

  • With reactive expression:
dataInput <- reactive({
  getSymbols(input$symb, src = "yahoo", 
             from = input$dates[1],
             to = input$dates[2],
             auto.assign = FALSE)
})

output$plot <- renderPlot({
  chartSeries(dataInput(), theme = chartTheme("white"), 
              type = "line", log.scale = input$log, TA = NULL)
})
  • A reactive expression saves its result the first time you run it.

  • The next time the reactive expression is called, it checks if the saved value has become out of date (i.e., whether the widgets it depends on have changed).

  • If the value is out of date, the reactive object will recalculate it (and then save the new result).

  • If the value is up-to-date, the reactive expression will return the saved value without doing any computation.