Extra Exercises
These optional five-minute exercises consolidate the eight lessons. Choose a relevant task; they are not extra requirements inside the 100-minute core plan. Work in pairs, ask for a prediction before execution and take two reasoned responses from the room. Learners can continue independently using Additional Material.
Exercise 1: Preserve IDs while Selecting Measurements
Use after: Lesson 2: Research Data. Goal: select records without losing identity or units.
Input: this fictional teaching table:
samples <- data.frame(
sample_id = c("A", "B", "C"),
mass_g = c(2.1, 2.4, 1.8),
checked = c(TRUE, FALSE, TRUE)
)- 1 min: predict which IDs have
checked == TRUE. - 2 min: select those rows and retain
sample_idandmass_g. - 1 min: compare the selected IDs, order and values with the source.
- 1 min: two pairs explain why a table of masses alone would weaken the handover.
Keep: the selected table and source check. If access fails: mark the retained rows on the displayed table.
checked_samples <- samples[samples$checked, c("sample_id", "mass_g")]
stopifnot(identical(checked_samples$sample_id, c("A", "C")))
stopifnot(isTRUE(all.equal(checked_samples$mass_g, c(2.1, 1.8))))The output retains A and C in source order. The check should account for identifiers and values; successful execution alone would not reveal that the wrong records were selected.
Exercise 2: Give a Function a Known-Value Check
Use after: Lesson 3: Functions. Goal: document and test a conversion before reuse.
Input: the session’s fahr_to_celsius() function and known values 32 °F = 0 °C and 212 °F = 100 °C.
- 1 min: identify the input and output units.
- 2 min: test both known values and a vector containing them.
- 1 min: add a comment explaining the units and missing-value expectation.
- 1 min: two pairs report a check that would detect an incorrect offset.
Keep: the function comment and tests. If access fails: substitute the known values into the displayed formula.
fahr_to_celsius <- function(temp) {
(temp - 32) * (5 / 9)
}
stopifnot(isTRUE(all.equal(fahr_to_celsius(32), 0)))
stopifnot(isTRUE(all.equal(fahr_to_celsius(212), 100)))
stopifnot(isTRUE(all.equal(fahr_to_celsius(c(32, 212)), c(0, 100))))These checks establish the expected results for the selected cases. A missing input produces a missing value with this implementation; whether that is acceptable belongs in the workflow’s input contract.
Exercise 3: Reuse a Function inside a Loop
Use after: Lesson 4: Iteration. Goal: separate one selection from its repetition.
Input: gapminder::gapminder and country names Ireland and Brazil.
- 1 min: describe what changes between the two selections.
- 2 min: create a function selecting one country, then call it inside a loop and keep the resulting tables in a named list.
- 1 min: check that each table contains its named country and retains
year. - 1 min: two pairs explain which part would need changing to support another country.
Keep: the helper function, loop and checked tables. If access fails: trace the two iterations on paper.
select_country <- function(dat, country_name) {
dat[as.character(dat$country) == country_name, ]
}
countries <- c("Ireland", "Brazil")
tables <- setNames(vector("list", length(countries)), countries)
for (country_name in countries) {
tables[[country_name]] <- select_country(gapminder::gapminder, country_name)
stopifnot(all(as.character(tables[[country_name]]$country) == country_name))
stopifnot("year" %in% names(tables[[country_name]]))
}The function implements one selection; the loop supplies different names. Keep the original data and identifiers unchanged. An unrecognised country can produce an empty table, so inspect the number of selected rows before assuming success.
Exercise 4: Explain the Level of a Grouped Summary
Use after: Lesson 5: Wrangling. Goal: state the observations and weighting behind a summary.
Input: the packaged Gapminder table, restricted to the recorded year 2007.
- 1 min: inspect the year and observation level.
- 2 min: group by continent and calculate country counts and mean life expectancy.
- 1 min: compare one group’s count and mean with a direct calculation on its source rows.
- 1 min: two pairs explain whether the mean gives equal weight to countries or individual people.
Keep: the summary and a sentence about its weighting. If access fails: annotate the instructor’s table and identify the records combined by one group.
library(dplyr)
selected <- gapminder::gapminder %>% filter(year == 2007)
summary_table <- selected %>%
group_by(continent) %>%
summarise(n_countries = n_distinct(country), mean_life_exp_years = mean(lifeExp))
stopifnot(sum(summary_table$n_countries) == nrow(selected))The mean weights country observations equally. It is not a population-weighted global or continental mean. The count check accounts for rows under the known country–year key; a direct value comparison is still needed to check the calculation.
Exercise 5: Notebook Parameter Review
Use after: Lesson 7. In a five-minute pair task, spend one minute predicting the effect of changing the year, two minutes rendering the supplied report for a different recorded year, one minute checking narrative/table/figure alignment and one minute hearing two pairs explain a fragile manually copied value. Keep the parameter record and check. If access fails, compare the instructor’s two prepared reports. The selection and inline expressions should change together; the input stays unchanged.
Exercise 6: Dashboard Failure Review
Use after: Lesson 8. Spend one minute predicting an empty selection, two minutes trying it and restoring a country, one minute comparing the restored observation with the source and one minute hearing two pairs explain why an empty choice is not a zero measurement. Keep a test case and observed state. A shared-screen or screenshot comparison is a valid fallback; check what it can and cannot establish.