-
Notifications
You must be signed in to change notification settings - Fork 1
/
slides.Rmd
256 lines (198 loc) · 11 KB
/
slides.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
---
title: "Making interactive web-apps in R using Shiny"
author: "Stuart Lacy"
date: "2022-03-02"
output:
binb::metropolis:
keep_tex: false
classoption: "aspectratio=169"
urlcolor: blue
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
## Introduction
- \alert{Allow others to explore the output of your R code through a web browser!}
- \alert{Learning objective}: understand what Shiny is, the potential uses it has for research, and be able to create a basic app after this talk
- Assumes you have some familiarity with R, but no experience with web development is required
- \alert{Follow along} with the examples by cloning this repository within RStudio:
- File -> New Project -> Version Control -> Git -> Repository URL: `https://github.com/stulacy/shiny-introduction.git`
## What is Shiny?
- An R package for creating \alert{web-apps}
- Developed by the RStudio/tidyverse team
- Designed with a focus on \alert{data visualisation}
## Why would I want to use it?
- Very \alert{quick development time} for initial proof of concepts
- Provide means for non-R users to access your work
- Don't need to know any HTML/CSS/JS, but can use those skills for \alert{customisation}
- Clean and modern looking default appearance
- Have access to R's extensive libraries
- Simple \alert{hosting} options
## Possible use cases
- Interactively visualize and \alert{explore} datasets (rather than generating PDFs with hundreds of figures)
- \alert{Monitor} live data streams
- Provide \alert{tools} to accompany published research (either methods, models, or data)
- Establish an online presence
- Provide visual interface to R code (i.e. automatic report generation)
- Examples:
- [COVID-19 dashboard](https://vac-lshtm.shinyapps.io/ncov_tracker/)
- [Genome browser](https://gallery.shinyapps.io/genome_browser/)
- [MRI Visualization](https://haozhu233.shinyapps.io/shinyMRI-contest/)
- [Lego Mosaic Creator](https://rpodcast.shinyapps.io/shinylego/)
# Shiny code layout
## What does Shiny code look like?
\begin{itemize}
\item<1-> Shiny apps are organised into \alert{2 files}:
\item<1-> \alert{$ui.R$} (\textbf{U}ser \textbf{I}nterface)
\begin{itemize}[<1->]
\item Defines the appearance of the app to end users (\alert{frontend})
\item Every UI is composed of multiple \alert{``widgets''}
\item Widgets can be \alert{outputs} such as plots, tables, text
\item And \alert{inputs} such as buttons, sliders, text fields, etc...
\end{itemize}
\item<2-> \alert{$server.R$}
\begin{itemize}[<2->]
\item Defines all \alert{backend} logic needed to process incoming inputs and generate the required outputs
\item Majority of your R code lives here
\end{itemize}
\item<3-> Input widgets are defined by \texttt{xInput} function calls in the UI
\item<3-> Output widgets are referenced in both the UI (\texttt{xOutput} functions) and in the server (\texttt{renderX})
\end{itemize}
## Example 1: Basic working example
- `examples/1_basic/`
- Example application with a single plot and table
- No interactivity at all
- Can look at the code either on GitHub or can clone it to your PC [https://github.com/stulacy/shiny-introduction](https://github.com/stulacy/shiny-introduction)
- Can run the app locally either by opening the project in RStudio, or can simply run `shiny::runGitHub(repo="shiny-introduction", username="stulacy", subdir="examples/1_basic")`
## Example 2: Interactive output elements
- There are many options for \alert{interactive} output widgets:
- `plotly`: general plotting library with controls
- `DataTables`: interactive tables
- `leaflet`: maps
- `networkD3`: network diagrams
- `diagrammeR`: graphs and flowcharts
- `r2d3`: Interface to D3 Javascript plotting library
- `examples/2_interactive_widgets`
- The same layout as example 1, but with an interactive plot and table
# Reactivity
## Example 3: Reactive user inputs
- The main form of adding interactivity in Shiny apps is through \alert{reactive} connections between the UI and Server
- Input UI elements are referenced in `server.R` through the `input` object, e.g. the current value of a dropdown menu
- Whenever this value changes due to user input, any output widgets that reference it will \alert{re-evaluate} and pass their new output (plot, table etc...) back to the UI
- `examples/3_reactivity`
## Example 4: Multiple reactive dependencies
- There is a \alert{many:many} relationship between input and outputs. Each `input` can be used in multiple outputs (as seen in previous example), and likewise each `output` can reference multiple `inputs`
- There are lots of possible \alert{input widgets}:
- Buttons
- Checkboxes
- Date selection/range
- File upload
- File download
- Text input
- Radio buttons
- Dropdown menu
- Sliders
- `examples/4_multiple_reactives`
## Example 5: Custom reactive objects
- So far we've seen that `input` objects are reactive and will \alert{trigger a change} in any downstream output that uses them
- You can also \alert{create your own} reactive elements in a variety of ways
- \alert{Be careful} when there are lots of reactive elements, it can make your code hard to follow and your app possibly slow!
- `examples/5_custom_reactivity`
## Reactivity chaining
\begin{columns}[T,onlytextwidth]
\column{0.5\textwidth}
Example 4
\begin{itemize}
\item User selects transform or variable
\item Simultaneously:
\begin{itemize}
\item Scatter plot transforms selected variable and is redrawn
\item Density plot transforms selected variable and is redrawn
\end{itemize}
\end{itemize}
\column{0.5\textwidth}
Example 5
\begin{itemize}
\item User selects transform or variable
\item $transformed\_df$ transforms selected variable
\item Simultaneously:
\begin{itemize}
\item Scatter plot is redrawn
\item Density plot is redrawn
\end{itemize}
\end{itemize}
\end{columns}
## More reactive objects
- Alternatively can use the `observe` and `reactiveValues` paradigm, useful when have multiple reactive items or when the reactive object has stateful characteristics
- This can be a complex topic, so refer to the [Shiny documentation](https://shiny.rstudio.com/articles/reactivity-overview.html) for more details
\footnotesize
```{r eval=F, echo=T}
updated_vals <- reactiveValues()
observe({
# Observe is triggered when any reactive expression contained within triggers
# Unlike reactive, it doesn't return anything
raw_val <- iris[[input$xvar]]
funcs <- list("None"=identity, "Squared"=function(x) x**2, "Log"=log)
transformed <- funcs[[input$transform]](raw_val)
label <- sprintf("Displaying variable %s with transform %s", input$xvar, input$transform)
updated_vals$data <- transformed
updated_vals$label <- label
})
```
# Customising your app's appearance
## Structuring UI
- By default all Shiny apps are \alert{responsive}, i.e. they adapt their layout to the size of the viewing device
- To add more structure to an app, you can use a `sidebarLayout` to \alert{separate} inputs from outputs
- You can partition your app further with \alert{tabbed output} using `tablistPanel`
- You can create entirely independent \alert{pages} with `navbarPage`
## Example 6: UI Sidebar
- `examples/6_ui_sidebar`
- Shows an example of adding a \alert{sidebar} to an app
- Useful for separating user controls from the resultant outputs
## Example 7: UI Tabs
- `examples/7_ui_tabs`
- Shows how separate UIs can be accessed through \alert{tabs}
## Example 8: UI Pages
- `examples/8_ui_pages`
- When a stronger distinction between different UIs is required, \alert{pages} can be used instead of tabs
## Further visual customisation
- You can organise elements into rows (`fluidRow`) and columns (`column`)
- The \alert{bslib} package provides different themes if you get bored of the default
- \alert{shinydashboard} package provides new UI elements for creating \alert{dashboard} style displays
- Can add \alert{CSS} to have fine control over each element's appearance
- Add flourishes with \alert{Javascript} (`shinyjs` package provides some useful features such as loading spinners)
## Example 9: Shinydashboard
- `examples/9_shinydashboard`
- Shows how the example 8 app looks under the `shinydashboard` package
- The UI elements provided by `shinydashboard` are designed to get a quick dashboard up and running in a more structured manner than using the default UI
# Other considerations
## Organising larger apps
- You can \alert{dynamically create UI elements} in the server end using `renderUI` and `uiOutput`
- Code can start to get disorganised with larger multi-page apps - recommend putting each page into its own files and using `source` to load them in ([example here](https://github.com/stulacy/RDES-Shiny/blob/master/app.R)) or using [modules](https://shiny.rstudio.com/articles/modules.html)
- If your program is running slower than expected, have a look at the \alert{reactive dependencies} and see if there is any redundancy
- Bear in mind that each time a plot is updated through user interaction, a new plot needs to be generated and downloaded from the server - can be CPU intensive if done very frequently or a big dataset!
## Hosting:
- University provide \alert{free hosting} at shiny.york.ac.uk
- 2 methods:
- \alert{Managed}: provide access to a GitHub repo and it will automatically update whenever there is a change to the main branch
- \alert{Self-hosted}: you are given access to a folder where you can put your app and any dependencies/data you need
- Email `itsupport@york.ac.uk` for access
- NB: not designed for a large number of concurrent users
- Shinyapps.io has free hosting for up to 5 apps provided by RStudio team
## Data storage:
- Several options for storing data
- \alert{CSV/other structured files}
- On same machine
- Or remote (through AWS, Google Drive, or even Google Sheets)
- \alert{Database} on same machine (SQLite) or remote (Postgres/MySQL/SQLServer etc...)
- Databases are useful for big datasets as they only load the requested subsets into memory, rather than having to read the full file
- Always worth doing as much pre-processing as possible \alert{offline}!
## Similar alternatives
- Dash (Python)
- Observable (Javascript/D3)
- Tableau (drag and drop, commercial)
- Grafana (drag and drop, open-source)
## Conclusions
- Biggest \alert{strength}: Shiny makes it easy to get apps up and running with a wide range of features to cover most use cases
- Biggest \alert{weakness}: For larger apps, the code can become hard to navigate, particularly if you start adding in custom JS/HTML/CSS
- If you need support come along to a Research Coding Club drop-in session or ask on our slack channel `#research-coding-club`. Join the mailing list at [https://researchcodingclub.github.io/](https://researchcodingclub.github.io/)