class: center, middle, inverse, title-slide # Shiny Part 1: Build! ##
FISH 497 ### Megsie Siple ### NOAA AFSC - RACE/GAP ### 2021/03/01 (updated: 2021-02-28) --- class: center, middle # Hello! --- class: center, middle ![sempe](img/sempe.jpg) --- # Marine science is like an orchestra Each musician has areas where they’re very specialized, and areas where they are clueless -- What we do is a combination of highly technical skilled work and more whimsical multitasking/communicating -- But we’re all working together to try to make a big, beautiful thing happen --- class: center, middle ![os1](img/OSSCS1.jpg) <sub><sup>Photo: Shaya Lyon</sup></sub> --- class: center, middle ![os2](img/OSSCS2.jpg) <sub><sup>Photo: Shaya Lyon</sup></sub> --- # How we deal with complexity in an orchestra setting: ### Clean it up ### Use building blocks ### Streamline our communications ### People are the special ingredient -- ## <mark>This is the same in marine science! Shiny can help us with many of these tasks.</mark> --- class: center, middle Shiny can be a little gnarly at first. ![stinkspirit](https://i.gifer.com/TR2i.gif) --- # Outline 1. `shiny` basics - when to use it, how to do it -- 2. Some features you can use to improve functionality User uploads & downloads Making interactive plots using `{plotly}` -- 3. Lessons I learned from developing "mmBIET" -- If you'd like to follow along, clone this directory and follow the examples! [https://github.com/mcsiple/shinyoverview](https://github.com/mcsiple/shinyoverview) -- There are many other things available in the repo that we won't cover today, but examples are included so you can try them on your own: > 4. *Translating your Shiny apps using `{shiny.18n}`* > 5. *Using Shiny to supercharge your remote teaching with `{learnr}`* > 6. *Generating Markdown reports from Shiny* --- # Why I learned Shiny ![dolphins](img/Common_Striped_Boyd.jpg) .caption[ **Image:** Jeff Moore ] --- # Why I learned Shiny ![mmbiet](img/mmbiet.gif) --- # What is Shiny? ![whatisshiny](img/whatisshiny.png) --- # When is Shiny useful? When we want to make R code accessible outside of an R or RStudio environment. For example, -- - teaching a package -- - showing data visualizations to non-experts -- - streamlining certain code-intensive things (like database queries or visualizing bulky simulation outputs) --- # Starting a new Shiny app Install **shiny**: ```r install.packages("shiny") ``` From The RStudio IDE, pick `New File -> Shiny Web App` You can choose between single (**app.R**) or multiple files (**ui.R** and **server.R**) *Does it matter which one you choose?* >Not really. Some people like the organization of having multiple files. But it really doesn't make a difference! ![poll](img/filepoll.png) --- # Each Shiny app has two components The **`ui`** (user interface) object dictates the appearance of the app. UI functions write HTML. For something to appear in your app, it needs to be in the UI. *** The **`server()`** function contains rendering expressions that create the objects to display. The server function and UI object are passed to the `shinyApp()` function to create a Shiny app object. --- # **ui.R**/server.R .pull-left[ The ui looks like this: ```r ui <- fluidPage( titlePanel("Old Faithful Geyser Data"), sidebarLayout( sidebarPanel( * sliderInput("bins", "Number of bins:", min = 1, max = 50, value = 30)), mainPanel( * plotOutput("distPlot")) ) ) ``` ] .pull-right[ The corresponding ui looks like this: ![basicui](img/basicui.png) ] --- # **ui.R**/server.R The ui code contains the following information: 1. The UI type - `fluidPage()` puts elements in rows that can include columns 🍰 - `navbarPage()` has a navigation bar 📁 2. Layout elements (`sidebarLayout()` etc.) 3. Theme information (e.g., `{shinythemes}`) -- 4. Output objects (`plotOutput()`, etc.) 5. Input objects (`sliderInput()`,`fileInput()` etc.) - also called "widgets" *Input objects link the user interface to the R code on the server.* --- # ui.R/**server.R** The server builds a list-like object called `output`. The contents of `output` are displayed in the ui. ```r server <- function(input, output) { output$distPlot <- renderPlot({ # generate bins based on input$bins from ui.R x <- faithful[, 2] bins <- seq(min(x), max(x), length.out = input$bins + 1) # draw the histogram with the specified number of bins hist(x, breaks = bins, col = 'darkgray', border = 'white') }) } ``` --- # **ui.R**/**server.R** The server builds a list-like object called `output`. `output` objects are displayed in the ui. Here is how they are linked: .pull-left[ ```r server <- function(input, output) { * output$distPlot <- renderPlot({ # generate bins based on input$bins from ui.R x <- faithful[, 2] bins <- seq(min(x), max(x), length.out = input$bins + 1) # draw the histogram with the specified number of bins hist(x, breaks = bins, col = 'darkgray', border = 'white') }) } ``` ] .pull-right[ ```r ui <- fluidPage( titlePanel("Old Faithful Geyser Data"), sidebarLayout( sidebarPanel( sliderInput("bins", "Number of bins:", min = 1, max = 50, value = 30)), mainPanel( * plotOutput("distPlot")) ) ) ``` ] --- # What's on the server? R code... mostly :) -- ![spirited](https://i.gifer.com/3QvT.gif) --- # ui.R/**server.R** - **Rendering functions** (`renderPlot()`, `renderTable()`, etc.) - Build a new object to display every time the inputs change -- - **Reactive expressions** - `reactive()` caches reactive objects so you can access them later in the server logic -- very important! - `eventReactive()` creates reactive objects but only when a specific input changes (e.g., a "Run Analysis!" button is clicked) - lazy -- - **Observe expressions** change the ui based on input, e.g., - autopopulate default values in a form if a user has selected a default - change the range for one input based on another input - eager --- class: center, middle # 01_basics/app.R --- class: center, middle, inverse # Getting data into and out of Shiny --- # Get data into a Shiny app Shiny can accept data from various file types. You can get data into Shiny from: - a file the user uploads - a database - a persistent file packaged with your app --- # User uploads data If you want to design your app so that people can bring in their own data: Add a file upload input in the UI using the function `fileInput()`. In the `server` function, access the uploaded files via `input$mydata`: ```r ui <- fluidPage( titlePanel("Uploading Files"), sidebarLayout( sidebarPanel( # refer to input$mydata in the server code to reference this object: fileInput("mydata", "Choose CSV File", multiple = FALSE, accept = c("text/csv", "text/comma-separated-values,text/plain", ".csv")), ``` --- # Put the data on the server You can publish small data files that sit on the server with your app. You can load these data at the top of the app file (if server and ui are both located in **app.R**) or in the **ui.R** file if you're using separate files for ui and server. --- # More on data storage in Shiny Dean Attali's [Persistent Data Storage With Shiny](https://daattali.com/shiny/persistent-data-storage/) app [This](https://shiny.rstudio.com/articles/persistent-data-storage.html) blog post about data storage in Shiny (also by Dean Attali) RStudio's [best practices for dashboards](https://db.rstudio.com/best-practices/dashboards/) shows how to connect a `shinydashboard` to a database --- # Downloading from Shiny You can download data from a Shiny app using `downloadLink()` or `downloadButton()` in the ui and `downloadHandler()` in the server: ```r ui <- fluidPage( downloadLink("downloadData", "Download") ) server <- function(input, output) { # Our dataset data <- mtcars output$downloadData <- downloadHandler( filename = function() { paste("data-", Sys.Date(), ".csv", sep="") }, content = function(file) { write.csv(data, file) } ) } ``` --- # Downloading from Shiny - Download **CSV or txt files** from Shiny apps -- - Generate reports in Markdown that are knitted to **html** (details on how to do that [here](https://shiny.rstudio.com/articles/generating-reports.html)) -- - You can also download **images** that have been generated in the app (e.g., download plots from the app) --- class: center, middle # 02_dataindataout/explore_ram/ui.R --- # Sidebar: Shiny dashboards Show a dataset several ways in one place (and automatically update it!) Use it for: - communicating data in a polished way - offering access to visualizations from a database - showing a "data story" in a linear way ![confdash](img/confdash.png) --- class: center, middle # Lessons I learned from developing a Shiny app ![droplets](https://i.gifer.com/g5.gif) --- # UI is very important Designing a good ui is hard! And Shiny defaults are not the most intuitive / appealing / accessible version they can be. -- If you are designing an app for management, a good ui is essential. -- - my #1 tip: if you have time, pilot test with subject matter experts AND users -- - check accessibility using the app's URL using the [Web Accessibility Evaluation (WAVE) Tool](https://wave.webaim.org/) -- - use UX resources if they are available! -- - if your institution doesn't have UX resources, design pilot testing so that you get helpful feedback on UX: - [18F Methods](https://methods.18f.gov/validate/) and [Maze](https://maze.design/guides/usability-testing/questions/) have great lists of testing questions and methods - 18F Methods also has an [example agreement](https://methods.18f.gov/participant-agreement/) for testers - Depending on the final format, places like [UsabilityHub](https://usabilityhub.com/) have interfaces that will provide data on clicks and scrolling behavior when testing is remote --- class: center, middle # Fin! ### contact ✉️: mcsiple@gmail.com 🐦: @margaretsiple ### **More Shiny resources:** [Mastering Shiny](https://mastering-shiny.org/) by Hadley Thee Wickham Colin Fay has several [talks](https://colinfay.me/talks-publications/) on Shiny app workflow and production We love a [cheatsheet](https://shiny.rstudio.com/images/shiny-cheatsheet.pdf) ### Some of my Shiny apps The [Marine Mammal Bycatch Impacts Exploration Tool](https://msiple.shinyapps.io/mammaltool/) [Novel-gazing](https://msiple.shinyapps.io/NovelGazingApp/) (for Goodreads users) [Adopt Don't Shop](https://nsilbiger.shinyapps.io/AdoptDontShop/) (collaboration with Nyssa Silbiger) *** Slides created using the R package [**xaringan**](https://github.com/yihui/xaringan).