```{r setup, include=FALSE}
knitr::opts_chunk$set(cache = FALSE)
```

## Acknowledgement

- Dr. Hua Zhou's [slides](https://raw.githubusercontent.com/ucla-biostat203b-2020winter/ucla-biostat203b-2020winter.github.io/master/slides/11-shiny/shiny.Rmd)

- [Shiny Documents](https://bookdown.org/yihui/rmarkdown/shiny-documents.html)

- [Mastering Shiny](https://mastering-shiny.org/index.html) by Hadley Wickham

## Why Shiny?

- Better presentations of data and ideas!
    - One of the most critical skills for data scientists.

- Browse the [Gallery](http://shiny.rstudio.com/gallery/) of Shiny apps.

- Shiny is a framework for creating web applications using R code.

  - No prior knowledge required for HTML, CSS or JavaScript

## Interactive documents

R Markdown documents can also generate interactive content.
There are two types of interactive R Markdown documents:

- the HTML Widgets framework

- the Shiny framework

### HTML widgets

The HTML Widgets framework is implemented in the R package `htmlwidgets`, interfacing JavaScript libraries that create interactive applications, such as interactive graphics and tables.

Several widget packages have been developed based on this framework

- `DT`

- `leaflet`

- `dygraphs`

Visit [https://www.htmlwidgets.org/](https://www.htmlwidgets.org/) for more HTMLwidgets for R.

```{r out.width='100%', echo=FALSE}
library(leaflet)
leaflet() %>% addTiles() %>%
  setView(-90.12274999048809, 29.93538150744488, zoom = 17) %>%
  addPopups(
    -90.12274999048809, 29.93538150744488,
    'Here is the <b>Department of Mathematics</b>, Tulane University'
  )
```

### Shiny documents

The `shiny` package builds interactive web apps powered by R.

To call Shiny code from an R Markdown document, add `runtime: shiny` to the YAML metadata, like in this document.

## Inputs and outputs 

Recall Diamonds is a data set available from ggplot2.
```{r}
library(tidyverse)
diamonds
```

### Numeric input, table output

To dynamically display the first rows:
```{r, echo = TRUE}
numericInput("rows", "How many diamonds?", 5)

renderTable({
  head(diamonds, input$rows)
})
```

### Slider input, plot output

To dynamically tune the histogram of variable `carat`:
```{r, echo = TRUE}
sliderInput("bins", "Number of bins:", min = 1, max = 300, value = 30)

renderPlot({
  ggplot(data = diamonds) +
    geom_histogram(mapping = aes(x = carat), bins = input$bins)
})
```

----

- Check the [Shiny cheat sheet](https://github.com/rstudio/cheatsheets/raw/master/shiny.pdf) for a list of inputs and outputs.

## Building a Shiny app

Shiny app is a standalone app. 

- Basic parts of a shiny app: <http://shiny.rstudio.com/articles/basics.html>

- How to build a shiny app: <http://shiny.rstudio.com/articles/build.html>

- How to launch a shiny app: <http://shiny.rstudio.com/articles/running.html>

----

- Skeleton of a Shiny app:
    ```{r, echo = TRUE, eval = FALSE}
    library(shiny)
    ui <- fluidPage()
    server <- function(input, output) {}
    shinyApp(ui = ui, server = server)
    ```

- 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.

## Shiny app: first example

- In RStudio, `File` -> `New File` -> `Shiny Web App...` creates a demo Shiny app using the `faithful` data set in base R. Recall the `faithful` data
    ```{r}
    head(faithful)
    ```

## Shiny app: censusVis

- This example is from tutorial: <http://shiny.rstudio.com/tutorial/written-tutorial/lesson5/>

- `counties.rds` contains demographic data for each county in the United States from 2010 census:
    ```{r}
    counties <- readRDS("census-app/data/counties.rds")
    head(counties)
    ```

----

- Use `maps` package, `mapproj` package and `helpers.R` file to plot maps:
    ```{r, message = FALSE}
    library(maps)
    library(mapproj)
    source("census-app/helpers.R")
    percent_map(counties$white, "darkgreen", "% White")
    ```

----

- Shiny app.
    ```{r, echo = FALSE, eval = FALSE}
    #setwd("census-app")
    #shinyAppDir(getwd())
    #shinyAppDir("census-app")
    #source("./census-app/app.R")
    runApp("census-app")
    ```

- [Code](https://github.com/tulane-math-7360-2023/tulane-math-7360-2023.github.io/tree/master/lectures/14-shiny/census-app) for the Shiny app `census-app`.

Let's take a closer look at the `census-app` code:
```{r, eval = FALSE}
# Load packages ----
library(shiny)
library(maps)
library(mapproj)

# Source helper functions -----
source("helpers.R")

# Load data ----
counties <- readRDS("data/counties.rds")

# User interface ----
ui <- fluidPage(
  titlePanel("censusVis"),
  
  sidebarLayout(
    sidebarPanel(
      helpText("Create demographic maps with 
               information from the 2010 US Census."),
      
      selectInput("var", 
                  label = "Choose a variable to display",
                  choices = c("Percent White", "Percent Black",
                              "Percent Hispanic", "Percent Asian"),
                  selected = "Percent White"),
      
      sliderInput("range", 
                  label = "Range of interest:",
                  min = 0, max = 100, value = c(0, 100))
    ),
    
    mainPanel(plotOutput("map"))
  )
)

# Server logic ----
# server function is run once each time a user visits the app
server <- function(input, output) {
  # renderPlot is run once each time a user changes a widget that output$map depends on
  output$map <- renderPlot({
    data <- switch(input$var, 
                   "Percent White" = counties$white,
                   "Percent Black" = counties$black,
                   "Percent Hispanic" = counties$hispanic,
                   "Percent Asian" = counties$asian)
    
    color <- switch(input$var, 
                    "Percent White" = "darkgreen",
                    "Percent Black" = "black",
                    "Percent Hispanic" = "darkorange",
                    "Percent Asian" = "darkviolet")
    
    legend <- switch(input$var, 
                     "Percent White" = "% White",
                     "Percent Black" = "% Black",
                     "Percent Hispanic" = "% Hispanic",
                     "Percent Asian" = "% Asian")
    
    percent_map(data, color, legend, input$range[1], input$range[2])
  })
}

# Run app ----
shinyApp(ui, server)
```

----

- 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.

## Shiny app: reactive expressions

- This example is from tutorial: <http://shiny.rstudio.com/tutorial/written-tutorial/lesson6/>

- [Code](https://github.com/tulane-math-7360-2023/tulane-math-7360-2023.github.io/tree/master/lectures/14-shiny/stockVis) for the Shiny app `stockVis`.

---

- Without using reactive expression:
    ```{r, eval = FALSE}
    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**:
    ```{r, eval = FALSE}
    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.
