-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathlearnr-demo.Rmd
416 lines (316 loc) · 11.1 KB
/
learnr-demo.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
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
---
title: "Learnr Demo"
output:
learnr::tutorial:
progressive: true
allow_skip: true
css: "css/style.css"
runtime: shiny_prerendered
---
```{r setup, include=FALSE}
# load packages
library(learnr)
library(gradethis)
library(sortable)
library(tidyverse)
library(learnrhash)
library(showtext)
library(googlesheets4)
# load data
ikea <- read_csv("data/ikea.csv")
# don't echo chunks
knitr::opts_chunk$set(echo = FALSE)
# apply theme to ggplot
ggplot2::theme_set(theme_bw())
```
## Introduction
*This is a demo tutorial for the [Designing the Data Science Classroom](https://rstudio-conf-2022.github.io/teach-ds/) workshop at rstudio::conf 2022.*
### Packages
We will use the **tidyverse** package in this tutorial. Run the code below to load the package.
```{r load-package, exercise = TRUE}
library(tidyverse)
```
### Data: Ikea furniture
The data set is all about [Ikea](https://www.ikea.com/) furniture. It was obtained from the [TidyTuesday](https://github.com/rfordatascience/tidytuesday/blob/master/data/2020/2020-11-03/readme.md) data collection.
Run the code below to see the data.
```{r load-data, exercise = TRUE}
ikea
```
We will primarily use the following variables in the analysis:
- `category`: The furniture category that the item belongs to (Sofas, beds, chairs, Trolleys,...)
- `price_usd`: Price in US dollars based on the price on the Ikea website on 4/20/2020.
Run the code to see the names of all variables in the data set, and [click here](https://github.com/rfordatascience/tidytuesday/blob/master/data/2020/2020-11-03/readme.md) to see the full data dictionary.
```{r colnames, exercise = TRUE}
names(ikea)
```
## Part 1: Question types
### Multiple choice questions
Below are side-by-side boxplots comparing the price of three categories of furniture at Ikea.
```{r}
ikea |>
filter(category %in% c("Tables & desks", "Sofas & armchairs", "Beds")) |>
ggplot(aes(x = category, y = price_usd, fill = category)) +
geom_boxplot() +
guides(fill = "none") +
labs(x = "Furniture category",
y = "Price (in $)")
```
```{r variability}
question("Which furniture category has the least variability in the price?",
answer("Beds"),
answer("Sofas & armchairs"),
answer("Tables & desk", correct = TRUE),
answer("The variability is the same for all three categories")
)
```
You can add options to allow retries, random order, and hints for incorrect responses.
```{r variability-hint}
question("Which furniture category has the largest IQR?",
answer("Beds"),
answer("Sofas & armchairs", correct = TRUE),
answer("Tables & desk"),
answer("The IQR is the same for all three categories"),
incorrect = "The IQR is the difference between the first and third quartiles.",
allow_retry = TRUE,
random_answer_order = TRUE
)
```
### Coding exercises
What is the most common furniture category?
```{r count-category, exercise = TRUE}
```
### Coding exercises with starter code
You can use starter code to provide scaffolding for coding exercises, and there are [multiple options](https://rstudio.github.io/learnr/articles/exercises.html) to customize the exercise input box.
What is the median price of furniture in the most common category?
```{r median-price, exercise = TRUE, exercise.lines = 5}
ikea |>
filter(____) |>
summarise(___)
```
### Exercises with hints
You can add hints to coding exercises.
Consider the categories `Sofas & armchairs` and `Tables & desks`. Which category has the highest mean price?
```{r avg-price, exercise = TRUE, exercise.lines = 5}
ikea
```
```{r avg-price-hint-1}
ikea |>
filter(category %in% c(____)) |>
____ |>
____
```
```{r avg-price-hint-2}
ikea |>
filter(category %in% c("Sofas & armchairs", "Tables & desks")) |>
group_by(___) |>
___
```
```{r avg-price-hint-3}
ikea |>
filter(category %in% c("Sofas & armchairs", "Tables & desks")) |>
group_by(category) |>
summarise(mean_price = mean(price_usd))
```
### Sorting questions
Use the [**sortable**](https://rstudio.github.io/sortable/) package to create sorting and ranking questions.
```{r sorting-exercise}
# Define the answer options
baking_steps <- c("Mix the ingredients.",
"Bake the cake.",
"Decorate the cake.",
"Slice the cake.")
# Write the exercise
question_rank(
"Sort the steps for making a cake in the correct order.",
answer(baking_steps, correct = TRUE),
answer(rev(baking_steps), correct = FALSE, message = "Other direction!"),
allow_retry = TRUE
)
```
## Part 2: Your turn!
::: your-turn
Create a tutorial with three questions:
- one multiple choice
- one coding exercise
- one sortable question
<b>Stretch goal:</b> Add hints to the coding exercise.
You can write your questions in this section of `learnr-demo.Rmd`.
:::
## Part 3: Automated feedback
So far students have to check their solutions to coding exercises by assessing whether the output is reasonable or comparing their code to the hints. You can add automated feedback on coding exercises using the [gradethis](https://pkgs.rstudio.com/gradethis/) package.
### Checking code
Count the number of items in the data set that cost more than \$300.
```{r gt300, exercise = TRUE}
```
```{r gt300-solution}
ikea |>
filter(price_usd > 300) |>
nrow()
```
```{r gt300-check}
grade_this_code()
```
### Checking output
Count the number of items in the data set that cost more than \$300. Submit the response as a single number, not in a data frame.
```{r gt300-pt2, exercise = TRUE}
```
```{r gt300-pt2-solution}
ikea |>
filter(price_usd > 300) |>
nrow()
```
```{r gt300-pt2-check}
grade_this({
pass_if_equal(
ikea |> filter(price_usd > 300) |> nrow(),
message = "Great work! You found the number of furniture items greater that cost more than $300!")
fail_if_equal(nrow(ikea),
message = "You found the number of observations in the data, but did you forget to filter for those that cost more than $300?")
fail("Not quite but keep trying!")
})
```
## Part 4: Your turn!
::: your-turn
Add automated feedback to your coding exercise.
**Stretch goal**: Consider 2 -3 common errors students may make. Write specific feedback for those errors.
You can write your responses in this section or modify the code in Part 2 of `learnr-demo.Rmd`.
:::
## Part 5: Minute paper
Provide a "minute paper" in an embedded online form for students to reflect on their understanding of the material in the tutorial.
```{=html}
<iframe src="https://docs.google.com/forms/d/e/1FAIpQLScsV-_m3unjj1S-NSsMjBir-yxrObaLbdS3ypzTe1tPoYv8gQ/viewform?embedded=true" width="640" height="550" frameborder="0" marginheight="0" marginwidth="0">Loading…</iframe>
```
## Part 6: Recording responses with learnrhash
Use the [**learnrhash**](https://github.com/rundel/learnrhash) package to collect student responses from learnr tutorials. Students submit their responses using a "hash" submitted to an online form.
Create a histogram of the distribution of Ikea furniture prices, then answer the following questions based on the histogram.
```{r price-histogram, exercise = TRUE}
ggplot(___, aes(x = ___)) +
___() +
labs(
___ = "Price (in $)",
___ = "Frequency",
___ = "Distribution of Ikea furniture prices"
)
```
```{r price-histogram-hint-1}
ggplot(ikea, aes(x = ___)) +
___() +
labs(
___ = "Price (in $)",
___ = "Frequency",
___ = "Distribution of Ikea furniture prices"
)
```
```{r price-histogram-hint-2}
ggplot(ikea, aes(x = price_usd)) +
___() +
labs(
___ = "Price (in $)",
___ = "Frequency",
___ = "Distribution of Ikea furniture prices"
)
```
```{r price-histogram-hint-3}
ggplot(ikea, aes(x = price_usd)) +
geom_histogram() +
labs(
___ = "Price (in $)",
___ = "Frequency",
___ = "Distribution of Ikea furniture prices"
)
```
```{r price-histogram-solution}
ggplot(ikea, aes(x = price_usd)) +
geom_histogram() +
labs(
x = "Price (in $)",
y = "Frequency",
title = "Distribution of Ikea furniture prices"
)
```
```{r price-histogram-check}
grade_this_code(
correct = "You correctly made the plot! Note that there is a warning that we will discuss in class."
)
```
```{r mc1}
question(
"Which of the following describes the shape of the distribution of Ikea furniture prices? Check all that apply.",
answer("Right skewed",
correct = TRUE
),
answer("Left skewed",
message = "Skew is on the side of the longer tail"
),
answer("Symmetric",
message = "If you were to draw a vertical line down the middle of the x-axis, would the left and right sides of the distribution look like mirror images?"
),
answer("Unimodal",
correct = TRUE
),
answer("Bimodal",
message = "How many prominent peaks do you see?"
),
answer("Multimodal",
message = "How many prominent peaks do you see?"
),
random_answer_order = TRUE
)
```
```{r mc2}
question(
"Which of the following is false?",
answer("The mean price is expected to be lower than the median price of Ikea furniture.", correct = TRUE),
answer("Less than 25% of the observations have prices greater than $1000."),
answer("The IQR is less than $1000."),
answer("The median price is less than $1000."),
random_answer_order = TRUE
)
```
### Submit answers
```{r context="server"}
encoder_logic(strip_output = TRUE)
```
```{r encode, echo=FALSE}
encoder_ui(
ui_before = div(strong("Once you're done with your quiz, click on Generate Submission below, copy the hash generated and paste it in the form below."), br(), br()),
ui_after = iframe_ui(
src = "https://forms.gle/w6hUr4j7tSdvRYtr7",
width="700px", height= "600px"
)
)
```
### Decode hash
The following would not be included in a student facing tutorial, but has been included here to demonstrate the decoding functionality of the [**learnrhash**](https://github.com/rundel/learnrhash) package.
```{r context="server"}
decoder_logic()
```
```{r decode, echo=FALSE}
decoder_ui()
```
### View data
You can view the collected data [here](https://docs.google.com/spreadsheets/d/1aEJxhOTHzUXdngrSOrntoyK8Suptj7Z_U7-8B4k1XBU/edit?usp=sharing).
<iframe width="900" height="400" src="https://docs.google.com/spreadsheets/d/e/2PACX-1vQjut2uPmkXsRpXSbbjSjQ68oGtw596Gxmb6kS079ZFxMoKqlc_xY3l66egsAvcXLP-XzDyPKwXpdqf/pubhtml?gid=333624434&single=true&widget=true&headers=false">
</iframe>
```{r, warning = FALSE, message = FALSE}
gs4_deauth() #deauthorize to read googlesheets
# read in responses
submissions <- read_sheet("ttps://docs.google.com/spreadsheets/d/1aEJxhOTHzUXdngrSOrntoyK8Suptj7Z_U7-8B4k1XBU/edit?resourcekey#gid=333624434") |>
rename(student_name = `Name`,
student_id = `Student ID`,
hash = `Copy and paste the hash generated at the end of your tutorial below.`) |>
select(-Timestamp)
```
### Process student submissions
You can process the student data in R to review student answers, calculate assignment scores, identify common
```{r}
submission_data <- extract_hash(submissions)
submission_data
```
<br>
Example of the data in the `answer` column.
```{r}
submission_data$answer[1]
submission_data$answer[2]
submission_data$answer[3]
```