---
title: "Shiny"
author: "JJB + Course"
date: "11/12/2018"
output:
   html_document:
     toc: true
     toc_float:
       collapse: false
runtime: shiny
---

# Lists

## Example: List Creation

```{r}
# Create a list with different data types
x = list(
  c(1, 2, 3),
  "text",
  c(1.3, 2.5),
  list(c(TRUE, FALSE)),
  list(c(-1, -5))
)

# Only has a length
length(x)

# Notice NULL is presence on dim
dim(x)
```

## Example: Mixed (Heterogenous) Function Return

```{r}
return_list = function(a, b, c) {
                             # ||  Unnamed value
  list(element1 = a, toad = b, c )
       # ^^^^^       ^^^^  Named values 
}

# Emphasize the mixing of data types
out = return_list(1:3, c("a", "b"), c(2 + 3i, 4 - 1i))
out
```

We could have achieved the above using:

```{r}
out = list(1:3, c("a", "b"), c(2 + 3i, 4 - 1i))
```

The emphasis, however, was on how a list could be beneficial in the scope of a
function.

## Example: Accessing List Items

```{r}
# Retrieve by name the list item called `element1`
out$element1

# Retrieve by position the list item called `element1`
out[[1]]

# Update value
out$element1 = c(5L, 42L, -2L) 

# Alternatively, we could use:
# out[[1]] = c(5L, 42L, -2L) 

# View values
out[[1]]
```


## Example: Preserving vs. Simplifying List Structure

```{r}
# Single brackets retain the list structure around item
out[2]

# Double bracket remove the list structure around item
out[[2]]

# Dollar signs also remove the list structure around item
out$toad
```


Let's explore what happens when we subset a `list` with
the single bracket operator.

```{r}
who_i_am = list(name = "James",
                job = "Instructor",
                pay = "Not enough",
                course = 385,
                "drones")

who_i_am[["name"]]

# Notice in environment it's a value
my_name = who_i_am[["name"]]

# Notice we've created another "Data" object
# that can be inspect via the magnifine glass.
my_name_list = who_i_am["name"]
```

We can see a similar pattern of simplification of data structures during other subset operations.


```{r}
a = data.frame(x = 1:10, y = 2:11)

# Returns a vector
a[, 1]

# Returns a data frame with column
a[, 1, drop = FALSE]


# Errors:
# Reduced to an atomic vector so, we cannot use $ to extract.
# a[, 1]$x

# This would work still as we have maintained the underlying data structure of a data.frame
a[, 1, drop = FALSE]$x
```


Unfortunation, the preservation of list structure doesn't quite follow the same semantics established with subsetting other elements.


```{r}
my_mat = matrix(1:10, nrow = 5)

my_mat

my_mat[1, ]

my_mat[1,, drop = FALSE]
```



# Building a Shiny App

## Minimal Shiny

```{r}
library(shiny)

# Define UI ----
ui = fluidPage(
       # Make a page layout
)

# Define server logic ----
server = function(input, output) { 
    # Backend logic
    # Retrieve values from input 
    # Save values to output 
    # Both are lists that are accessed with input$ and output$
}

# Launch the App
shinyApp(ui = ui, server = server )
```

## Layout Mock

```{r}
library("shiny")

# Define UI ----
ui = fluidPage(
    titlePanel("My Shiny App Title"),  # Title
    sidebarLayout(
      sidebarPanel(
        h1("SideBar Title")            # Sidebar Text
      ),                               # Note HTML
      mainPanel("Main Content")        # Content Text
    ) # close: sidebarLayout()
  ) # close: fluidPage()

# Define server logic ----
server = function(input, output) { 
  # Not used
}

# Launch the App
shinyApp(ui = ui, server = server )
```


```{r}
h1('My first heading')
```


## HTML UI App Example

```{r}
# Taken from: https://shiny.rstudio.com/tutorial/written-tutorial/lesson2/

library(shiny)

# Define UI ----
ui = fluidPage(
  titlePanel("My Star Wars App"),
  sidebarLayout(
    sidebarPanel(),
    mainPanel(
      h6("Episode IV", align = "center"),
      h6("A NEW HOPE", align = "center"),
      h5("It is a period of civil war.", align = "center"),
      h4("Rebel spaceships, striking", align = "center"),
      h3("from a hidden base, have won", align = "center"),
      h2("their first victory against the", align = "center"),
      h1("evil Galactic Empire.", align = "right")
    )
  )
)

# Define server logic ----
server = function(input, output) {
  
}

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

## Add Inputs to UI

```{r}
library("shiny")

# Define UI ----
ui = fluidPage(
    titlePanel("Data Summarizer"),                          # Title
    sidebarLayout(
      sidebarPanel(
        h3("Data Selection"),                               # Note the , 
        
        # Dropdown Menu with fixed Choices
        selectInput(inputId = "ds",                         # Name
                    label = "Choose a dataset:",            # Label
                    choices = c("iris", "Spam", "mtcars")), # Choices
        
        # Numeric Field
        numericInput(inputId = "obs",                       # Name
                     label = "Number of Obs:",              # Label
                     value = 10),                           # Default Value
        
        submitButton("Load Preview Data")                   # Update data
      ), # close: sidebarPanel()
      mainPanel("Main Content")                             # Content
    ) # close: sidebarLayout()
) # close: fluidPage(



# Define server logic ----
server = function(input, output) {
  
}

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


## Adding Output Areas to UI

```{r}
library("shiny")

# Define UI ----
ui = fluidPage(
    titlePanel("Data Summarizer"),                          # Title
    sidebarLayout(
      sidebarPanel(
        h3("Data Selection"),                               # Note the , 
        
        # Dropdown Menu with fixed Choices
        selectInput(inputId = "ds",                         # Name
                    label = "Choose a dataset:",            # Label
                    choices = c("iris", "Spam", "mtcars")), # Choices
        
        # Numeric Field
        numericInput(inputId = "obs",                       # Name
                     label = "Number of Obs:",              # Label
                     value = 10),                           # Default Value
        
        submitButton("Load Preview Data")                   # Update data
      ), # close: sidebarPanel()
       mainPanel(
        h3("Head of the Dataset"),                          # HTML
        tableOutput("view"),                                # Table View
    
        h3("Dataset Summary"),                              # HTML
        verbatimTextOutput("summary")                       # Output Asis
        ) # close: mainPanel()
    ) # close: sidebarLayout()
) # close: fluidPage(



# Define server logic ----
server = function(input, output) {
  
}

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


## UI to Server Mapping

```{r}
library("shiny")
library("datasets") # for Spam data

data("Spam", package = "datasets")

# Define UI ----
ui = fluidPage(        
        # Dropdown Menu with fixed Choices
        selectInput(inputId = "ds",                           # Name
                             label = "Choose a dataset:",   # Label
                             choices = c("iris", "Spam", "mtcars")),
        verbatimTextOutput("summary")               # Output Asis
) # close: fluidPage(

# Define server logic ----
server = function(input, output) {

  output$summary = renderPrint({   # Summary Render
    summary(get(input$ds))
  }) # close: renderPrint()

}

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


## Final Shiny App

```{r}
library("shiny")
library("datasets") # for Spam data

# Define UI ----
ui = fluidPage(
    titlePanel("Data Summarizer"),        # Title
    sidebarLayout(
      sidebarPanel(
        h3("Data Selection"),             # Note the , 
        
        # Dropdown
        selectInput("ds",                 # Name
                    "Choose a dataset:",  # Label
                    choices = c("iris", "Spam", "mtcars")),
        
        numericInput("obs",               # Name
                     "Number of Obs:",    # Label
                     10),                 # Default Value
        
        submitButton("Load Preview Data") # Update data
      ), # close: sidebarPanel()
      mainPanel(
        h3("Head of the Dataset"),    # HTML
        tableOutput("view"),          # Table View
        
        h3("Dataset Summary"),        # HTML
        verbatimTextOutput("summary") # Output Asis
      ) # close: mainPanel()
    ) # close: sidebarLayout()
  ) # close: fluidPage(

# Define server logic ----
server = function(input, output) {
  
  active_dataset = reactive({   # Reactive
    if(input$ds == "iris") {
      iris
    } else if (input$ds == "Spam") {
      Spam
    } else {
      mtcars
    }
  }) # close: reactive()
  
  output$summary = renderPrint({   # Summary Render
    summary(active_dataset())
  }) # close: renderPrint()
  
  output$view = renderTable({      # Table Render
    head(active_dataset(), n = input$obs)
  }) # close: renderPrint()
  
}

# Launch the App
shinyApp(ui = ui, server = server)
```

## Exercise: Making a plot

```{r}
library(shiny)

# Define UI ----
ui = fluidPage(
  h1("Grapher"),
  sidebarLayout(
    sidebarPanel(
      # insert a numeric input 
      numericInput(inputId = "nrows",
                   label = "Number of Rows",
                   value = 5)
    ),
    mainPanel(
      # insert an output type for plotting 
      plotOutput(outputId = "data_graph")
    )
  )
)

# Define server logic ----
server = function(input, output, session) {
  # Assignment: Plot the first input$nrows columns of a
  # data frame of your choosing, using head() and plot()
  # 
  # Hint: You may need to load another library at the top of the file ;-)
  
  output$data_graph = renderPlot({
    ggplot( head(cars, n = input$nrows) ) +
      geom_point(aes(speed, dist))
  })
}

# Launch the App
shinyApp(ui, server)
```


## Exercise: Refractoring Code to use a Conductor

```{r}
library(shiny)
library(ggplot2)

# Define UI ----
ui = fluidPage(
  h1("Grapher with Reactivity"),
  sidebarLayout(
    sidebarPanel(
      numericInput("nrows", "Number of rows", 10, min = 1)
    ),
    mainPanel(
      plotOutput("plot"),
      tableOutput("table")
    )
  )
)

# Define server logic ----
server = function(input, output, session) {
  # Assignment: Factor out the cars[sample(nrow(cars), input$nrows),] so
  # that the code isn't duplicated and the operation isn't
  # performed twice for each change to input$nrows.
  
  subset_data = reactive({
    # Move out the random sampling
    # to a shared cache.
    cars[sample(nrow(cars), input$nrows),]
  })
  
  output$plot = renderPlot({
    ggplot(
      subset_data()
      ) +
      geom_point(aes(speed, dist))
  })
  
  output$table = renderTable({
    subset_data()
    })
}

# Launch the App
shinyApp(ui, server)
```

