Dataset Reference
This appendix documents every dataset used across all five chapters, so you can look one up whenever you forget its structure. It also includes the script that regenerates every custom dataset from scratch, in case your copies get lost or modified.
5 Custom Course Datasets
student_scores
Used in: Chapters 1–2. A small gradebook-style dataset.
#> 'data.frame': 40 obs. of 5 variables:
#> $ id : int 1 2 3 4 5 6 7 8 9 10 ...
#> $ name : chr "Student_01" "Student_02" "Student_03" "Student_04" ...
#> $ group : chr "A" "A" "A" "B" ...
#> $ score : int 63 66 49 89 69 95 92 69 77 92 ...
#> $ hours_studied: num 4.7 5.3 4.6 4.4 1.5 4.5 1.4 7.3 3 5.3 ...
| Column | Meaning |
|---|---|
id |
Student identifier |
name |
Student name |
group |
Class section (A or B) |
score |
Exam score, 0–100 |
hours_studied |
Self-reported study hours |
Also provided as data/student_scores.xlsx and data/student_scores.txt for import practice.
course_dataset
Used in: Chapters 3–5. The “running dataset” for the whole second half of the course — a simulated clinical trial.
#> 'data.frame': 180 obs. of 14 variables:
#> $ id : chr "P001" "P002" "P003" "P004" ...
#> $ site : chr "Site C" "Site B" "Site A" "Site C" ...
#> $ treatment : chr "New" "Standard" "New" "Standard" ...
#> $ age : int 59 68 33 53 58 49 42 40 67 49 ...
#> $ sex : chr "Male" "Male" "Male" "Male" ...
#> $ activity_level : chr "Moderate" "High" "Moderate" "Low" ...
#> $ baseline_pain : num 8.7 6.7 7.6 5.5 6 4.1 6.8 6 5.8 6.6 ...
#> $ week4_pain : num 5.8 6.5 3.9 2.7 5.9 4.6 6.6 2.5 4.4 2.9 ...
#> $ week8_pain : num 5.1 5.6 0.1 2.4 5.1 4.6 4.2 2.4 3.5 1.3 ...
#> $ response : chr "Responder" "Non-Responder" "Responder" "Responder" ...
#> $ symptom_pre : chr "Present" "Absent" "Present" "Present" ...
#> $ symptom_post : chr "Absent" "Present" "Present" "Absent" ...
#> $ rater1_severity: chr "Severe" "Mild" "Moderate" "Severe" ...
#> $ rater2_severity: chr "Severe" "Mild" "Moderate" "Severe" ...
| Column | Meaning |
|---|---|
id |
Patient identifier |
site |
Hospital site (A/B/C) — the stratifying variable for CMH |
treatment |
Standard or New |
age, sex |
Demographics |
activity_level |
Ordinal: Low/Moderate/High — used for trend tests |
baseline_pain, week4_pain, week8_pain |
Pain scores (0–10) at three time points — used for bootstrap and Friedman examples |
response |
Responder/Non-Responder — the binary outcome |
symptom_pre, symptom_post |
Paired binary symptom status — used for McNemar |
rater1_severity, rater2_severity |
Two raters’ ordinal severity grades — used for kappa |
survey_income
Used in: Chapter 3, to illustrate a genuinely skewed variable.
#> 'data.frame': 100 obs. of 3 variables:
#> $ household_id : int 1 2 3 4 5 6 7 8 9 10 ...
#> $ region : chr "Urban" "Urban" "Rural" "Rural" ...
#> $ monthly_income: int 17581 5260 24417 22408 20646 19483 11935 24541 6938 30536 ...
6 Built-In R Datasets Used in This Book
These come with base R (or the datasets package, which is always loaded) — you never need to download or import them.
| Dataset | Used in | What it contains |
|---|---|---|
mtcars |
Ch. 1, 3 | 32 cars: mpg, horsepower, weight, and other specs |
iris |
Ch. 1 | 150 flowers: petal/sepal measurements across 3 species |
PlantGrowth |
Ch. 1, 5 | Plant weights under control vs. two treatments |
airquality |
Ch. 2 | Daily air quality measurements, New York, 1973 |
chickwts |
Ch. 2 | Chick weights under six different feed types |
InsectSprays |
Ch. 4 | Insect counts under six different spray types |
ToothGrowth |
Ch. 5 | Guinea pig tooth growth under two supplement types |
sleep |
Ch. 5 | Extra sleep hours under two drugs |
Load any of these with data(name) (though most are available immediately without even calling data()).
7 Regenerating All Custom Datasets
If your copies of the custom datasets are ever lost, corrupted, or you want to verify reproducibility, this script recreates all of them exactly (it uses a fixed random seed):
set.seed(2026)
## student_scores.csv
n1 <- 40
student_scores <- data.frame(
id = 1:n1,
name = paste0("Student_", sprintf("%02d", 1:n1)),
group = sample(c("A", "B"), n1, replace = TRUE),
score = round(pmin(100, pmax(0, rnorm(n1, mean = 68, sd = 14)))),
hours_studied = round(pmax(0, rnorm(n1, mean = 5, sd = 2)), 1)
)
write.csv(student_scores, "data/student_scores.csv", row.names = FALSE)
## course_dataset.csv
n2 <- 180
site <- sample(
c("Site A", "Site B", "Site C"),
n2, replace = TRUE, prob = c(.4, .35, .25)
)
treatment <- sample(c("Standard", "New"), n2, replace = TRUE)
age <- pmin(pmax(round(rnorm(n2, 52, 12)), 21), 85)
sex <- sample(c("Male", "Female"), n2, replace = TRUE, prob = c(.45, .55))
baseline_pain <- round(
pmin(10, pmax(0, rgamma(n2, shape = 6, rate = .9))), 1
)
effect <- ifelse(treatment == "New", 2.6, 1.4)
week4_pain <- round(
pmin(10, pmax(0, baseline_pain - rnorm(n2, effect, 1.1))), 1
)
week8_pain <- round(
pmin(10, pmax(0, week4_pain - rnorm(n2, effect * .5, 1.0))), 1
)
response <- ifelse(
(baseline_pain - week8_pain) / pmax(baseline_pain, .5) >= .3,
"Responder", "Non-Responder"
)
symptom_pre <- sample(
c("Present", "Absent"), n2, replace = TRUE, prob = c(.75, .25)
)
symptom_post <- ifelse(
response == "Responder",
sample(c("Present", "Absent"), n2, replace = TRUE, prob = c(.25, .75)),
sample(c("Present", "Absent"), n2, replace = TRUE, prob = c(.65, .35))
)
sev <- c("Mild", "Moderate", "Severe")
rater1 <- sample(sev, n2, replace = TRUE, prob = c(.3, .45, .25))
rater2 <- ifelse(
runif(n2) < .75, rater1, sample(sev, n2, replace = TRUE)
)
activity_level <- sample(
c("Low", "Moderate", "High"), n2, replace = TRUE, prob = c(.35, .4, .25)
)
course_dataset <- data.frame(
id = sprintf("P%03d", 1:n2), site, treatment, age, sex,
activity_level = factor(
activity_level, levels = c("Low", "Moderate", "High"), ordered = TRUE
),
baseline_pain, week4_pain, week8_pain, response, symptom_pre, symptom_post,
rater1_severity = factor(rater1, levels = sev, ordered = TRUE),
rater2_severity = factor(rater2, levels = sev, ordered = TRUE)
)
write.csv(course_dataset, "data/course_dataset.csv", row.names = FALSE)
## survey_income.csv
n3 <- 100
survey_income <- data.frame(
household_id = 1:n3,
region = sample(c("Urban","Rural"), n3, replace = TRUE),
monthly_income = round(rlnorm(n3, meanlog = 9.5, sdlog = .55))
)
write.csv(survey_income, "data/survey_income.csv", row.names = FALSE)
## exam_pairs.csv
n4 <- 25
pre <- round(rnorm(n4, 60, 10))
post <- round(pre + rnorm(n4, 8, 6))
exam_pairs <- data.frame(student_id = 1:n4,
pre_test = pmin(100, pmax(0, pre)),
post_test = pmin(100, pmax(0, post)))
write.csv(exam_pairs, "data/exam_pairs.csv", row.names = FALSE)8 Package Installation Checklist
install.packages(c(
"boot", "psych", "coin", "readxl", "tidyr", "dplyr", "ggplot2",
"tableone", "gtsummary", "BSDA", "PMCMRplus", "writexl"
))Every package marked eval=FALSE in code chunks throughout this book (mainly tableone, gtsummary, BSDA, and PMCMRplus) was not available in the environment this book was built in, but the code shown is exactly what you should run once you’ve installed them on your own machine.