-
Notifications
You must be signed in to change notification settings - Fork 6
/
scaling-functions.Rmd
147 lines (116 loc) · 5.19 KB
/
scaling-functions.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
# Functions
```{r, echo=FALSE}
htmltools::includeHTML("./partials/todo.html")
```
### Exercise 14.4.1 {-}
The following app plots user selected variables from the msleep dataset for three different types of mammals (carnivores, omnivores, and herbivores), with one tab for each type of mammal. Remove the redundancy in the `selectInput()` definitions with the use of functions.
```{r, eval=FALSE}
library(tidyverse)
ui <- fluidPage(
selectInput(inputId = "x",
label = "X-axis:",
choices = c("sleep_total", "sleep_rem", "sleep_cycle",
"awake", "brainwt", "bodywt"),
selected = "sleep_rem"),
selectInput(inputId = "y",
label = "Y-axis:",
choices = c("sleep_total", "sleep_rem", "sleep_cycle",
"awake", "brainwt", "bodywt"),
selected = "sleep_total"),
tabsetPanel(id = "vore",
tabPanel("Carnivore",
plotOutput("plot_carni")),
tabPanel("Omnivore",
plotOutput("plot_omni")),
tabPanel("Herbivore",
plotOutput("plot_herbi")))
)
server <- function(input, output, session) {
# make subsets
carni <- reactive( filter(msleep, vore == "carni") )
omni <- reactive( filter(msleep, vore == "omni") )
herbi <- reactive( filter(msleep, vore == "herbi") )
# make plots
output$plot_carni <- renderPlot({
ggplot(data = carni(), aes_string(x = input$x, y = input$y)) +
geom_point()
}, res = 96)
output$plot_omni <- renderPlot({
ggplot(data = omni(), aes_string(x = input$x, y = input$y)) +
geom_point()
}, res = 96)
output$plot_herbi <- renderPlot({
ggplot(data = herbi(), aes_string(x = input$x, y = input$y)) +
geom_point()
}, res = 96)
}
shinyApp(ui = ui, server = server)
```
:::solution
#### Solution {-}
We can see a pattern here where we are creating the same type of plot for each tabset panel, with the only variable changing being the `vore` argument. We can reduce everything we see in triplicate to functions! We can use `map` to create a single `create_panels` function which will create a tab for each of our `species`. On the server side, the data is filtered three times, and the plots are created three times. We can create a single rendering function that given the correct string it will filter the data, create the correct plot, and assign it to the correct output.
```{r, eval=FALSE}
library(tidyverse)
# use a vector for function inputs
species <- c("Carnivore", "Omnivore", "Herbivore")
# educe to a single UI function
# Marly: this didn't work!
create_panels <- function(id) {
tabPanel(id, plotOutput(paste0("plot_", id)))
}
ui <- fluidPage(
selectInput(inputId = "x",
label = "X-axis:",
choices = c("sleep_total", "sleep_rem", "sleep_cycle",
"awake", "brainwt", "bodywt"),
selected = "sleep_rem"),
selectInput(inputId = "y",
label = "Y-axis:",
choices = c("sleep_total", "sleep_rem", "sleep_cycle",
"awake", "brainwt", "bodywt"),
selected = "sleep_total"),
tabsetPanel(
tabPanel("Carnivore", plotOutput("plot_Carnivore")),
tabPanel("Omnivore", plotOutput("plot_Omnivore")),
tabPanel("Herbivore", plotOutput("plot_Herbivore"))
)
# this works without the tabsetPanel function - why?!
# purrr::map(species, create_panels)
)
server <- function(input, output, session) {
# rendering plot function for each panel
render_outputs <- function(id) {
output[[paste0("plot_", id)]] <- renderPlot({
msleep %>%
filter(vore == tolower(stringr::str_remove(id, "vore")) %>%
ggplot() +
aes_string(x = input$x, y = input$y) +
geom_point()
)
})
}
# apply to the species vector using map
purrr::map(species, render_outputs)
}
shinyApp(ui = ui, server = server)
```
:::
<!---------------------------------------------------------------------------->
<!---------------------------------------------------------------------------->
<!---------------------------------------------------------------------------->
### Exercise 14.4.2 {-}
Continue working with the same app from the previous exercise, and further remove redundancy in the code by modularizing how subsets and plots are created.
:::solution
#### Solution {-}
TODO: I'm unsure what to do with this one since we haven't yet introduced modules?
:::
<!---------------------------------------------------------------------------->
<!---------------------------------------------------------------------------->
<!---------------------------------------------------------------------------->
### Exercise 14.4.3 {-}
Suppose you have an app that is slow to launch when a user visits it. Can
modularizing your app code help solve this problem? Explain your reasoning.
:::solution
#### Solution {-}
No, we're just packaging our code into neater functions - this doesn't change or optimize what is loaded when the app is launched. In fact, modularizing might even make your application slower in some cases.
:::