class: center, middle, inverse, title-slide .title[ # Data analysis II ] .subtitle[ ## Shiny ] .author[ ### Laurent Bergé ] .institute[ ### University of Bordeaux, BxSE ] .date[ ### Fall 2022 ] --- class: section # Shiny --- # What's shiny Shiny is a framework to build .color1[interactive web pages]. You computer acts like a server and there is a back and forth between the browser and the server. --- ![](data:image/png;base64,#images/shiny/shiny_app.png) --- # Shiny: Why? Shiny is great to: - explore data / results - showcase results --- # Shiny: Strenghts - whatever R code can be run and included in the webpage (data processing, graphics, etc)! - it's an HTML page so you can include: - custom HTML - custom CSS - custom javascript --- # Shiny: Examples - [exploring patent data](https://www.shinyapps.io/admin/#/application/3057051) - [analyzing an event via twitter](https://apps.garrickadenbuie.com/rstudioconf-2019/) --- # Shiny: Resources - [RStudio's tutorials](https://shiny.rstudio.com/tutorial/) - [RStudio's examples]() - [Shiny cheat sheet](https://shiny.rstudio.com/images/shiny-cheatsheet.pdf) - [Many examples of Shiny apps](https://shiny.rstudio.com/gallery/) --- class: section # How it works --- # Components of an app ### 1 app = 2 documents .block[{ui.R} All the components of the HTML page. The code in this document generates a static HTML page. ] -- .block[{server.R} Contains all the R processing (data, graphs, etc). Code can execute when some events are triggered in the webpage. The code in this document can modify the HTML page. ] --- ![](data:image/png;base64,#images/shiny/ui_main.png) --- ![](data:image/png;base64,#images/shiny/ui_main_boxes.png) --- ![](data:image/png;base64,#images/shiny/server_main.png) --- ![](data:image/png;base64,#images/shiny/server_main_boxes.png) --- # ui.R The file `ui.R` sets up the stage. If we commented out the content of `server.R`, the app would look like: ![](data:image/png;base64,#images/shiny/ui_no_server.png) --- # ui - server: Explaining the example ### In the server - access ui elements using the `input$inputId` where `inputId` is the ID of an ui element of input type (all `inputId` must be unique!) - write into ui elements using `output$outputId` where `outputId` is the ID of an ui element of output type (all `outputId` must be unique!) -- ### Histogram In the previous histogram example, at startup: - the function in the server is run - `input$bins` is read - the value of `input$bins` is 30, it was set as the default in `ui.R` - an histogram is created with the appropriate number of bins - the plot is rendered in the ui element of output ID `distPlot` --- ![](data:image/png;base64,#images/shiny/ui_server_interaction.png) --- # Tying server output to ui elements In the example we had: .leftcol[ .color-192E5B.fs-22[ui.R] `plotOutput("distPlot")` ] .rightcol[ .color-192E5B.fs-22[server.R] `output$distPlot <- renderPlot({STUFF})` ] -- To display stuff in a .bold1[plotOutput] ui component, you must use a .bold1[renderPlot] function in the server. These functions work together! --- # ui-server relationships ![](data:image/png;base64,#images/shiny/ui_server_output.png) --- # Exercize Create a shiny (Web) app in RStudio: you'll get the default template we've been using (the histogram). 1. use `tableOutput`/`renderTable` to add the data set below the graph 2. use `textOutput`/`renderText` to display the number of observations in the data at the top of the main panel 3. replace the regular table by a *dataTable* using `dataTableOutput`/`renderDataTable`. --- class: section # Inputs --- # Shiny inputs Here are some very useful inputs: ![](data:image/png;base64,#images/shiny/ui_inputs.png) See the full list of inputs at: [https://shiny.rstudio.com/articles/cheatsheet.html](https://shiny.rstudio.com/articles/cheatsheet.html) --- # Exercize In the histogram app: - replace the slider by a numeric input --- class: section # Reactivity --- # When does it change? When you create your first app, you'll notice that whenever an input changes, the output changes. This is .color1[reactivity]. .block[{renderTYPE functions} In the render functions family (`renderPlot`, etc), anything of the form `input$id` is looked after. Whenever the value of `input$id` is modified by the user, the function is re-run (and the content in the HTML is updated). ] --- ![](data:image/png;base64,#images/shiny/server_reactive.png) --- # Reactivity: How to control it - sometimes we don't want the page to be updated any time the user changes something - this is especially true when the processing is costly - how can we add control? --- # Reactivity: Tools (server side) - use `isolate(input$<inputId>)` in a `renderTYPE` function to prevent the function to be updated when `input$<inputId>` changes - use `observeEvent({input$a; input$b}, {# do stuff})` to evaluate the code in the 2nd argument when data in the first argument changes (here the input IDs `a` or `b`) - use `eventReactive(input$a, {# function code})` to create a function whose body is the 2nd argument and which is re-run only when the data in the 1st argument changes --- # Exercize Using our histogram app: - add an `actionButton` in the left panel - make the histogram update .color1[only when the button is clicked] - add another button to randmly change the color of the histogram --- class: section # looks --- # tabsets A very common layout is the tabsets: ![](data:image/png;base64,#images/shiny/tabsets.png) --- # Exercize On our histogram app: - using `tabsetPanel`, create a page displaying the data, and another one displaying the histogram --- # Add HTML You can add HTML quite easily: use `tags$<HTML-tag>` ![](data:image/png;base64,#images/shiny/ui_html.png) --- # Stuff you must know: Use the server to change the UI The function `insertUI` can be used to insert arbitrary things. ```r # ui.R tags$div(id = "container") ``` ```r # server.R insertUI( selector= "#container", ui = tags$div( tags$h4("More inputs"), textInput("in_text", "Insert text"), actionButton("new_btn", "New button") ) ) ``` --- # Exercize Using our histogram app: - using `insertUI`, create a button to save the graph: when clicked, the current graph is replicated below itself and won't change any more - do the same as before but allow any number of graphs to be saved --- class: section # Conceive and share --- # Conceive your app You app is first and foremost an idea that needs to be operationalized. How it looks, how it is user-friendly .color1[matters a lot]. .strong1.center[This is best done with pen and paper!] --- # Sharing You can upload you app in: [http://www.shinyapps.io/](http://www.shinyapps.io/) That's super easy. --- # Going further ### Must read [Mastering Shiny](https://mastering-shiny.org/index.html) by Hadley Wickham