-
Notifications
You must be signed in to change notification settings - Fork 41
/
01-your_first_shiny_app.rmd
375 lines (271 loc) · 13.4 KB
/
01-your_first_shiny_app.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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
# Your first Shiny app
**Learning objectives:**
- Learn how to **create a simple Shiny app**
- Define the **leanest version** of an app you can build
- Review different **ways to start and stop** the app
- Identify the **two key components** of every Shiny app
- Understand how the two **components are connected**
- Observe how Shiny apps **react to user input**
## Introduction
This chapter is basically a quick demo of the minimum boilerplate needed for a Shiny app.
It defines the two key components - the **ui** and the **server**
Then introduces **reactive programming** - which is how shiny automatically updates outputs when inputs change.
Shiny outputs (tables, charts etc.) can automatically **react** (recalculate) when their inputs change.
![](images/01-your_first_shiny_app/basic_react.png)
### If you haven't installed Shiny already:
```{r install_shiny, eval=FALSE}
install.packages('shiny')
```
Check you have version 1.5.0 or higher
```{r check_package}
packageVersion("shiny")
```
Load shiny
```{r load_shiny, warning=FALSE}
library('shiny')
```
## Creating an app
Simplest way - create new directory for your app and add a single `app.r` file
```{r first_app, eval=FALSE}
library(shiny)
ui <- fluidPage(
"Hello, world!"
)
server <- function(input, output, session) {
}
shinyApp(ui, server)
```
Looking closely at the code above, this app.r file does four things:
1. Loads `shiny`
2. Defines the **ui** - the HTML webpage humans interact with
3. Specifies behaviour of the app in the **server**
4. Executes `shinyApp(ui, server)` to construct and start the app
## Running and stopping the app
The basic workflow of shiny app development is...
1. Write some code
2. Start the app
3. Play with the app
4. Write some more code
5. Repeat...
A simple diagram of the Shiny development process.
![](images/01-your_first_shiny_app/shiny-dev-process-simple.png)
### Running the app
There are a few ways you can run your app
*If using R Studio:*
- Click `Run App` button in document toolbar
- Keyboard shortcut is `CMD / CTRL + SHIFT + ENTER`
*If not using R Studio:*
- (source()) the whole document or call shiny::runApp()
The console message `#> Listening on http://127.0.0.1:3827` identifies your app in any (local) web browser.
- `127.0.0.1` is a standard address = this computer
- last 4 digits = randomly assigned port number
Running a Shiny app keeps R busy and you will not be able to execute other commands in the console at that time.
### Stopping the app:
- `STOP` sign on console toolbar
- `ESC` from within R console (`CTRL + C` is not in R Studio)
- Close shiny app window
## Adding UI controls
Replace the `ui` in your app with this code that shows you all the built-in data frames in the datasets package.
```{r ui_1, eval=FALSE}
ui <- fluidPage(
selectInput("dataset", label = "Dataset", choices = ls("package:datasets")),
verbatimTextOutput("summary"),
tableOutput("table")
)
```
Four new functions:
1. `fluidPage()` - **layout function** to set up visual structure of page
2. `selectInput()` - **input control** for user to interact with
3. `verbatimTextOutput()` - **output control** - shows code result
4. `tableOutput()` - **output control** - displays tables
**These are all just ways to generate HTML**
Run the following in the console to see the outputted html:
```{r html output, eval=FALSE}
selectInput("dataset", label = "Dataset", choices = ls("package:datasets"))
```
Open the app in the browser, `right click on page` \>\> `select inspect` to see the html.
**Note:** `fluidPage()` is just one option available for page setup. `navBarPage()` is a nice example for creating an app with page tabs.
You can see an example of the use of `navBarPage()` [here](https://shiny.rstudio.com/gallery/navbar-example.html).
## Adding behaviour
Need server function to bring the outputs to life
Reactive programming tells Shiny **how** to perform a function.
> It's the difference between giving someone a recipe versus demanding that they go make you a sandwich. \~ Hadley Wickham (Author of Mastering Shiny)
Your coding the range of app behaviors, but the user of your app demands the output based on their selection of input(s).
This code tells shiny how to fill in the `summary` and `table` outputs we defined in the UI.
```{r server_1, eval=FALSE}
server <- function(input, output, session) {
output$summary <- renderPrint({
dataset <- get(input$dataset, "package:datasets")
summary(dataset)
})
output$table <- renderTable({
dataset <- get(input$dataset, "package:datasets")
dataset
})
}
```
Each `output$out_id` is a new shiny output to render where the UI defines it
There are specific render functions `render{Type}` for different outputs:
- text
- tables
- plots
- images
- new ui components
## Reactive expressions
Key part of reducing duplication and ensuring you [D-R-Y (Don't-Repeat-Yourself)](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)
**Duplicated code is particularly bad for Shiny apps which can get cumbersome and more difficult to maintain and debug as they grow** (Although the latest release of shiny does have some improved debugging tools)
Reactive expressions combines some of the same logic as variables and functions, but is a bit different as these do not work the same in shiny as normal R programming.
Create a reactive expression by wrapping a block of code in `reactive({...})` and assigning it to a variable.
You can use the reactive expression like a standard function with **one important difference** - it only runs once and caches the result until the input is changed. So once it is initialised it will return some form of constant until it's updated again.
The below code retrieves the dataset once, not twice
```{r server_2, eval=FALSE}
server <- function(input, output, session) {
# Create a reactive expression
dataset <- reactive({
get(input$dataset, "package:datasets")
})
output$summary <- renderPrint({
# Use a reactive expression by calling it like a function
summary(dataset())
})
output$table <- renderTable({
dataset()
})
}
```
## Visualising reactive expressions
The flow visualised in 2.1 now has a middle layer - a reactive expression.
![](images/01-your_first_shiny_app/reactive_expression.png)
Which lives in the server function of the app. The ui to server connections can be visualised like this: ![](images/01-your_first_shiny_app/reactive_ui_server.png)
Using our 'first app' as an example:
![](images/01-your_first_shiny_app/reactive_ui_server_example.png)
A good way to see this in action is to use Shiny's showcase mode:
```{r showcase-example, eval=FALSE}
runApp("examples/01-your_first_shiny_app/app-data-example-final.R", display.mode = "showcase")
```
You can read more about the different Shiny display modes [here](https://shiny.rstudio.com/articles/display-modes.html).
## Shiny resources
Shiny cheatsheet
<https://www.rstudio.com/resources/cheatsheets/>
![](images/01-your_first_shiny_app/shiny-cheatsheet.pdf){width="150%"}
### Other resources
**Shiny Gallery** has lots of inspiration and demos of specific ui components and server behaviours. <https://shiny.rstudio.com/gallery/>
**Shiny Widgets Gallery** is included in above link and introduces the main options for inputs in the ui. <https://shiny.rstudio.com/gallery/widget-gallery.html>
**Shiny Dashboard** is a nice framework for creating good looking and well structured apps with minimal effort. May get limiting as you advance and want more customisation. <https://rstudio.github.io/shinydashboard/index.html>
## Meeting Videos
### Cohort 1
`r knitr::include_url("https://www.youtube.com/embed/U5C34S4MayQ")`
<details>
<summary> Meeting chat log </summary>
```
00:34:30 Tan Ho: (there are ways to get access to the R console!)
00:34:43 shamsuddeen: ?
00:35:13 Tan Ho: specifically re: Jerome's comment about R console being locked while an app is running
00:36:17 shamsuddeen: Ok. How can one access it ?
00:37:06 Tan Ho: probably a talk on its own
00:38:03 shamsuddeen: -:) I see !!!
00:38:40 Tan Ho: I might be able to do a presentation on debugging shiny a bit later in the bookclub
00:38:47 Tan Ho: I actually don't see a chapter on it...
00:39:18 shamsuddeen: Yaaaayyy Tan. That would be cool !!
00:41:36 Dave: Chapter 6.2 is about debugging
00:42:20 Tan Ho: Ah!
00:42:26 Arnab Dey (he/him): Do we have to define the ui before the server? The order seems a bit counter-intuitive
00:42:58 Tan Ho: arnab - it's not necessary but it's convention in shiny apps
00:43:16 Arnab Dey (he/him): got it!
00:43:46 shamsuddeen: Can you write shiny app in Rmarkdown?
00:45:32 priyanka gagneja: yes shamshudeen you can
00:45:56 shamsuddeen: Thanks Priyanka
00:52:17 Jessica Mukiri: Has anyone had a go at the exercises?
00:52:51 Russ Hyde: Have you a question about the exercises?
00:55:26 Jessica Mukiri: Question 4 for on the reactive expression
01:02:50 Federica Gazzelloni: thanks
01:02:57 Sarah Rathwell: Thanks
```
</details>
### Cohort 2
`r knitr::include_url("https://www.youtube.com/embed/UfYv0Jp4yIQ")`
<details>
<summary>Meeting chat log</summary>
```
# Meeting 2021-07-28
00:15:20 Ola: you are on mute
00:30:25 Ola: it sounds like you need to setup your ssh key
00:30:27 Ola: https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent
00:31:11 Conor Tompkins: RStudio sort of combines git add and git commit.
00:36:19 Ola: yes
00:46:54 Conor Tompkins: It would be interesting to know whether you can use a port number below 1023. Those are reserved for specific uses
00:48:15 Ola: You can assign an application a port number.
00:48:58 Ola: There are some default ports for certain applications like postgres I think its like port 5410 … don't quote me on that
00:49:45 Ryan Metcalf: Many APIs utilize particular ports when communicating to different servers. Redis, Postgres, SQLServer, etc…
00:49:52 Ryan Metcalf: HTML by default is 80 or 8080.
00:50:17 Ryan Metcalf: SSH, FTP, SFTP, are 21, 22, 23, etc…
00:51:35 Eileen: Shiny:: cheat sheet
00:54:43 Ola: Maybe we should have a debugging zoom party one of these days
```
</details>
### Cohort 3
`r knitr::include_url("https://www.youtube.com/embed/aDiOqqd1Ydc")`
<details>
<summary>Meeting chat log</summary>
```
00:06:57 Njoki Njuki Lucy: https://docs.google.com/spreadsheets/d/1YnFBY5nwSFoQuryPXtfmoguVbE4sIrjP_LhRLSZM8dc/edit#gid=0
00:17:24 Ryan Metcalf: https://github.com/r4ds/bookclub-mshiny
00:23:57 Njoki Njuki Lucy: https://docs.google.com/spreadsheets/d/1YnFBY5nwSFoQuryPXtfmoguVbE4sIrjP_LhRLSZM8dc/edit?usp=sharing
00:35:56 Njoki Njuki Lucy: https://mastering-shiny.org/
00:36:22 Ryan Metcalf: `git branch <repo name> # create branch
00:37:35 Ryan Metcalf: Forgive me, let me edit that line of code: `git remote add [name_of_your_remote] [name_of_your_new_branch]`
00:48:02 Mohit Soni: Hi All, I’m Mohit, logging in from India, I work with R in Supply Chain forecasting. Excited to meet fellow learners and learn together.
00:59:43 Njoki Njuki Lucy: https://docs.google.com/spreadsheets/d/1YnFBY5nwSFoQuryPXtfmoguVbE4sIrjP_LhRLSZM8dc/edit?usp=sharing
01:00:14 Ryan Metcalf: https://docs.google.com/spreadsheets/d/1YnFBY5nwSFoQuryPXtfmoguVbE4sIrjP_LhRLSZM8dc/edit#gid=0
```
</details>
`r knitr::include_url("https://www.youtube.com/embed/D0pUxWx6BZE")`
<details>
<summary>Meeting chat log</summary>
```
00:24:22 Ryan Metcalf: https://www.rstudio.com/about/platform-support/
00:58:04 Ryan Metcalf: Lucy’s Cohort Signup Sheet: https://docs.google.com/spreadsheets/d/1YnFBY5nwSFoQuryPXtfmoguVbE4sIrjP_LhRLSZM8dc/edit#gid=0
```
</details>
### Cohort 4
`r knitr::include_url("https://www.youtube.com/embed/AJh03Py6Tmk")`
<details>
<summary>Meeting chat log</summary>
```
00:05:00 Lucio: all good. excited to be here
00:08:39 Sarfaraz Jamal: I was introduced to shiny by my friend a few weeks ago.
00:08:44 Sarfaraz Jamal: so I wanted to learn more
00:11:09 Jon Harmon (jonthegeek): I'm going to hop off! Good luck, I love to see a new cohort get started!
00:11:32 Matthew Efoli: Thanks @Jon
00:12:07 novica nakov: Hi. I just joined because I noticed a new cohort and it seemed like there were people being late.
00:16:15 Trevin: Welcome Lydia!
00:16:32 Lydia Gibson: Hello!
00:25:55 Lucio: i use vs code
00:32:12 Lydia Gibson: no
00:32:35 Trevin: I’m in the Advanced R bookclub right now
00:35:06 Lance Christian: Did Matthew lose connection?
00:35:26 Trevin: I thought that was me, my internet went out before the meeting
00:35:34 Lydia Gibson: Me too
00:47:17 Trevin: It should be package:datasets
00:48:32 Lucio: line 11
00:51:03 Lucio: session is also used when one wants to send data from R to JavaScript, or the other way around
00:51:04 Trevin: Yeah, that makes sense thanks
01:02:41 Lydia Gibson: Thank you Matthew!
01:02:47 Lucio: thank you
01:02:48 Lucio: bye
01:02:49 Sarfaraz Jamal: thank you very much
```
</details>
### Cohort 5
`r knitr::include_url("https://www.youtube.com/embed/0TQ-rXYrRfE")`
<details>
<summary>Meeting chat log</summary>
```
00:24:15 Abdou: For now it’s clear
00:56:17 Oluwafemi Oyedele: https://github.com/nanxstats/awesome-shiny-extensions.
00:58:15 Abdou: Reacted to "https://github.com/n..." with 👍
00:58:26 Oluoch, Wyclife Agumba: Reacted to "https://github.com/n..." with 👍🏾
00:58:45 Oluoch, Wyclife Agumba: Amazing!
00:59:20 Jim: Very good presentation !
```
</details>