W1-M01 R as calculator
MOODLE SOURCE NOTE: pr01. Familiarisation (3).r · task 1. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 1 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
R distinguishes an expression from its printed result. Parentheses govern the order of operations, and the number [1] shown by the Console is a vector index, not part of the answer.
R evaluates parentheses before multiplication/division and then addition/subtraction. The [1] displayed in a Console result denotes the index of the first vector element; it is not part of the arithmetic answer. Compare print(6 + 1) with typing 6 + 1 directly into the Console.
Step-by-step classroom instructions
- Add 6 and 1, then print the result.
- Multiply 2 by the sum of 1 and 3, then print the result.
- Calculate 5 plus 3 times 2, then print the result.
Masterclass learning goals
Learning goal: Compute 6+1, 2*(1+3), then predict 5+3*2.
Concept: Arithmetic operators, operator precedence and parentheses.
Original task checklist
Task instructions — what the student must do
- Add 6 and 1, then print the result.
- Multiply 2 by the sum of 1 and 3, then print the result.
- Calculate 5 plus 3 times 2, then print the result.
Instructor's teaching method and common pitfalls
Ask learners to predict each number before executing. Comparing the second and third expression reveals the precedence rules.
Common trap / interpretation warning
Do not interpret R’s console prefix [1] as the result.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
R evaluates parentheses before multiplication/division and then addition/subtraction. The [1] displayed in a Console result denotes the index of the first vector element; it is not part of the arithmetic answer. Compare print(6 + 1) with typing 6 + 1 directly into the Console.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Add 6 and 1, then print the result.
# print(6 +
# Step 2. Multiply 2 by the sum of 1 and 3, then print the result.
# print(2 * (
# Step 3. Calculate 5 plus 3 times 2, then print the result.
# print(5 +Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Show the result in the Console (or display a ggplot object).
print(6 + 1) # Addition returns 7.
# NOTE: Show the result in the Console (or display a ggplot object).
print(2 * (1 + 3)) # Parentheses evaluated first; returns 8.
# NOTE: Show the result in the Console (or display a ggplot object).
print(5 + 3 * 2) # Multiplication precedes addition: 11.Expected output, excerpts and validation checks
[1] 7
[1] 8
[1] 11Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W1-M02 Assignment and reusable results
MOODLE SOURCE NOTE: pr01. Familiarisation (3).r · task 2. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 4 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- sum() Expanded reference ↗
- Add numeric values; optionally ignore missing values. Check argument names and data types before running the code.
sum(x, na.rm=FALSE) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - ls() Expanded reference ↗
- List names of objects currently in the R environment. Check argument names and data types before running the code.
ls() - <- Expanded reference ↗
- Assign the result of the right-hand expression to an object name.
name <- expression
Concepts, learning goals and student instructions
What this teaches — concept breakdown
The assignment arrow stores the result of an expression, so later instructions can reuse it instead of recomputing it. 1:10 creates an inclusive integer sequence.
The assignment operator <- stores a value in an object for subsequent statements. In R, 1:10 includes both endpoints; sum(1:10) is 55. Reusing x differs from recalculating the sum in every line. Check objects with ls(), and explain why names and values are different.
Step-by-step classroom instructions
- Add the integers from 1 to 10 and store the total in x.
- Divide the stored total x by 10 and print the result.
Masterclass learning goals
Learning goal: Save 1+...+10 as x. Divide x by ten.
Concept: Assignment, reusable objects, numeric sequences and the R environment.
Original task checklist
Task instructions — what the student must do
- Add the integers from 1 to 10 and store the total in x.
- Divide the stored total x by 10 and print the result.
Instructor's teaching method and common pitfalls
Contrast an object name (x) with the value it currently holds; show how changing x changes subsequent calculations.
Common trap / interpretation warning
ls() is session-dependent and may include other objects.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
The assignment operator <- stores a value in an object for subsequent statements. In R, 1:10 includes both endpoints; sum(1:10) is 55. Reusing x differs from recalculating the sum in every line. Check objects with ls(), and explain why names and values are different.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Add the integers from 1 to 10 and store the total in x.
# x <- sum(
# Step 2. Divide the stored total x by 10 and print the result.
# print(x /Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Assign the computed expression to x for reuse.
x <- sum(1:10) # 1:10 is an inclusive integer sequence; sum gives 55.
# NOTE: Show the result in the Console (or display a ggplot object).
print(x / 10) # Stored result re-used; expected 5.5.
# NOTE: Show the result in the Console (or display a ggplot object).
print(ls()) # List current objects; not the same as printing values.Expected output, excerpts and validation checks
[1] 5.5
# ls() also lists current object names; that list depends on the R session.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W1-M03 Text, numbers, vectors and indexing
MOODLE SOURCE NOTE: pr01. Familiarisation (3).r · task 3 and naming notes. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 4 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - mean() Expanded reference ↗
- Calculate an arithmetic average. Use na.rm=TRUE to omit missing values explicitly.
mean(x, na.rm=FALSE) - [ ] Expanded reference ↗
- Select one or more values by 1-based position or logical mask.
x[i]
Concepts, learning goals and student instructions
What this teaches — concept breakdown
Character values need quotation marks; the L suffix creates an integer literal. A logical mask is a TRUE/FALSE vector that selects entries at matching positions.
A vector typically stores values of a common atomic type; combining character and numeric elements can coerce types. R indexes from 1, unlike Python. A logical condition such as sleep_hours > 6 produces a TRUE/FALSE mask, and x[mask] retains only matching elements.
Step-by-step classroom instructions
- Store a short text label in course_label.
- Store the number of participants as an integer in participants.
- Create a numeric vector containing four fictional sleep durations.
- Print only the sleep durations greater than 6 hours using logical indexing.
Masterclass learning goals
Learning goal: Store a character, integer, and vector; extract values above six.
Concept: Character and numeric values; vectors, logical masks and indexing.
Original task checklist
Task instructions — what the student must do
- Store a short text label in course_label.
- Store the number of participants as an integer in participants.
- Create a numeric vector containing four fictional sleep durations.
- Print only the sleep durations greater than 6 hours using logical indexing.
Instructor's teaching method and common pitfalls
Have the learner evaluate sleep_hours > 6 before indexing and explain why R starts indexing at 1.
Common trap / interpretation warning
In sleep_hours[sleep_hours > 6], the condition is applied element by element.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
A vector typically stores values of a common atomic type; combining character and numeric elements can coerce types. R indexes from 1, unlike Python. A logical condition such as sleep_hours > 6 produces a TRUE/FALSE mask, and x[mask] retains only matching elements.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Store a short text label in course_label.
# course_label <-
# Step 2. Store the number of participants as an integer in participants.
# participants <-
# Step 3. Create a numeric vector containing four fictional sleep durations.
# sleep_hours <- c(
# Step 4. Print only the sleep durations greater than 6 hours using logical indexing.
# print(sleep_hours[Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Create a named value or vector that later steps can inspect.
course_label <- "PALS practice" # Character/string is enclosed in quotes.
# NOTE: Create a named value or vector that later steps can inspect.
participants <- 66L # L makes an integer literal.
# NOTE: Create a named value or vector that later steps can inspect.
sleep_hours <- c(6, 8, 7, 5) # c() combines values into a numeric vector.
# NOTE: Show the result in the Console (or display a ggplot object).
print(sleep_hours[1]) # R indices start at 1, not 0.
# NOTE: Show the result in the Console (or display a ggplot object).
print(sleep_hours[sleep_hours > 6]) # Logical indexing -> c(8, 7).
# NOTE: Show the result in the Console (or display a ggplot object).
print(mean(sleep_hours)) # Expected 6.5 hours, for illustrative data.Expected output, excerpts and validation checks
[1] 6
[1] 8 7
[1] 6.5Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W1-M04 Built-in USArrests data frame
MOODLE SOURCE NOTE: pr01. Familiarisation (3).r · task 5. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 4 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - dim() Expanded reference ↗
- Return dimensions, usually rows and columns. Check argument names and data types before running the code.
dim(x) - names() Expanded reference ↗
- Get or assign column or element names. Check argument names and data types before running the code.
names(data) - head() Expanded reference ↗
- Show the first n elements or rows. Check argument names and data types before running the code.
head(x, n=6)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
USArrests is an R built-in data frame with one row per US state and four crime-rate/urbanisation variables. dim(), names() and head() inspect its structure.
USArrests is a built-in teaching data frame. Each row is a US state and each column a variable. dim(data) reports rows and columns, names(data) returns variable names, and head(data) provides a first look without printing the entire table.
Step-by-step classroom instructions
- Assign the built-in USArrests dataset to an object called crime.
- Print the number of rows and columns in crime.
- Print all column names in crime.
- Print the first six rows of crime.
Masterclass learning goals
Learning goal: Load USArrests into crime; inspect variables and dimensions.
Concept: Data frames, observations (rows) and variables (columns).
Original task checklist
Task instructions — what the student must do
- Assign the built-in USArrests dataset to an object called crime.
- Print the number of rows and columns in crime.
- Print all column names in crime.
- Print the first six rows of crime.
Instructor's teaching method and common pitfalls
Distinguish rows (observations) from columns (variables); head() is a preview and does not alter the data.
Common trap / interpretation warning
Built-in datasets are useful for syntax practice, not evidence about present-day conditions.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
USArrests is a built-in teaching data frame. Each row is a US state and each column a variable. dim(data) reports rows and columns, names(data) returns variable names, and head(data) provides a first look without printing the entire table.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Assign the built-in USArrests dataset to an object called crime.
# crime <-
# Step 2. Print the number of rows and columns in crime.
# print(dim(
# Step 3. Print all column names in crime.
# print(names(
# Step 4. Print the first six rows of crime.
# print(head(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Assign a built-in teaching data frame to a working object.
crime <- USArrests # Built-in public teaching dataset, no CSV needed.
# NOTE: Show the result in the Console (or display a ggplot object).
print(dim(crime)) # Rows and columns: 50 by 4.
# NOTE: Show the result in the Console (or display a ggplot object).
print(names(crime)) # Murder, Assault, UrbanPop, Rape.
# NOTE: Show the result in the Console (or display a ggplot object).
print(head(crime)) # Display the first six rows.Expected output, excerpts and validation checks
[1] 50 4
[1] "Murder" "Assault" "UrbanPop" "Rape"
# head(crime) prints six state rows with four columns.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W1-M05 Functions, help and extraction
MOODLE SOURCE NOTE: pr01. Familiarisation (3).r · tasks 6–8. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 3 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - max() Expanded reference ↗
- Return the largest value. Check argument names and data types before running the code.
max(x, na.rm=FALSE) - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
Functions take arguments and return values. The $ operator accesses a named data-frame column; max() returns its largest value.
A function call has the form function_name(argument, named_argument=value). The $ operator extracts a named column from a data frame; max() finds the largest value. For datasets with missing values, na.rm=TRUE controls whether NA is omitted. Help pages document parameters and outputs.
Step-by-step classroom instructions
- Print the maximum value in the Murder column of crime.
- Print the Assault column (or a relevant element of it) using the dollar operator.
- Open R help for the max function.
Masterclass learning goals
Learning goal: Find the maximum Murder and Assault; inspect max() help.
Concept: Function calls, named arguments, the dollar operator and help pages.
Original task checklist
Task instructions — what the student must do
- Print the maximum value in the Murder column of crime.
- Print the Assault column (or a relevant element of it) using the dollar operator.
- Open R help for the max function.
Instructor's teaching method and common pitfalls
Contrast the complete Murder vector with max(crime$Murder), and use ?max to discover optional arguments.
Common trap / interpretation warning
A maximum is a descriptive statistic; it does not identify its row unless you inspect which state attained it.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
A function call has the form function_name(argument, named_argument=value). The $ operator extracts a named column from a data frame; max() finds the largest value. For datasets with missing values, na.rm=TRUE controls whether NA is omitted. Help pages document parameters and outputs.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Print the maximum value in the Murder column of crime.
# print(max(
# Step 2. Print the Assault column (or a relevant element of it) using the dollar operator.
# print(crime$
# Step 3. Open R help for the max function.
# help(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Show the result in the Console (or display a ggplot object).
print(max(c(2, 4, 6))) # max() needs a vector or individual numbers.
# NOTE: Show the result in the Console (or display a ggplot object).
print(crime$Murder) # $ extracts the column named Murder.
# NOTE: Show the result in the Console (or display a ggplot object).
print(max(crime$Murder)) # Expected 17.4 in USArrests.
# NOTE: Show the result in the Console (or display a ggplot object).
print(max(crime$Assault)) # Expected 337 in USArrests.
# Interactive help: type ?max or help("max") in the RStudio Console.Expected output, excerpts and validation checks
[1] 6
# print(crime$Murder) shows all 50 values (truncated here).
[1] 17.4
[1] 337Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W1-M06 Removing objects
MOODLE SOURCE NOTE: pr01. Familiarisation (3).r · task 9. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 3 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- rm() Expanded reference ↗
- Remove an object from the current R environment. Check argument names and data types before running the code.
rm(object) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - exists() Expanded reference ↗
- Check whether an object of the specified name exists. Check argument names and data types before running the code.
exists("x")
Concepts, learning goals and student instructions
What this teaches — concept breakdown
rm() removes an object from the current R environment; it does not delete a CSV or modify the built-in dataset. exists() checks whether a name is still defined.
rm(crime) removes the object only from the active R environment; it does not uninstall a package or delete a CSV file. Saving scripts that recreate objects is essential for reproducibility. exists("crime") tests the object’s presence after removal.
Step-by-step classroom instructions
- Remove the crime object from the current R environment.
- Print whether an object called crime still exists.
Masterclass learning goals
Learning goal: Remove crime from the environment.
Concept: Removing an in-memory object without deleting the source file.
Original task checklist
Task instructions — what the student must do
- Remove the crime object from the current R environment.
- Print whether an object called crime still exists.
Instructor's teaching method and common pitfalls
Ask what happens if the next command tries to use crime after rm(crime).
Common trap / interpretation warning
Running this section twice without recreating crime can fail because rm(crime) cannot find it.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
rm(crime) removes the object only from the active R environment; it does not uninstall a package or delete a CSV file. Saving scripts that recreate objects is essential for reproducibility. exists("crime") tests the object’s presence after removal.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Remove the crime object from the current R environment.
# rm(
# Step 2. Print whether an object called crime still exists.
# print(exists(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Remove the named object from the R environment.
rm(crime) # Remove only this named object from Environment.
# NOTE: Show the result in the Console (or display a ggplot object).
print(exists("crime")) # FALSE: object no longer exists.Expected output, excerpts and validation checks
[1] FALSEData-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W1-E01 Additional: reproducible report
MOODLE SOURCE NOTE: ferdo Lab original extension. INDEPENDENT ADDITION (not an official Moodle task).
R functions and syntax reference · 4 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - data.frame() Expanded reference ↗
- Build a rectangular data frame from named columns. Check argument names and data types before running the code.
data.frame(x=..., y=...) - seq_along() Expanded reference ↗
- Create integer indices from 1 through length(x). Check argument names and data types before running the code.
seq_along(x)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
A research question, a numeric vector and a data frame represent different kinds of information. A small fictional dataset is a safe way to practise reporting.
Distinguish the outcome variable (what is measured), predictor (a possible explanation), units, and a potential confounder (a factor associated with both). Fictional observational values are useful for teaching code but cannot establish a real causal claim.
Step-by-step classroom instructions
- Write a fictional research question and store it as a text value.
- Create a short numeric vector of fictional reaction times.
- Print a small data frame with trial numbers and reaction times.
Masterclass learning goals
Learning goal: Define the outcome, predictor, unit, and one possible confounder.
Concept: Research questions, variables, units and possible confounding.
Original task checklist
Task instructions — what the student must do
- Write a fictional research question and store it as a text value.
- Create a short numeric vector of fictional reaction times.
- Print a small data frame with trial numbers and reaction times.
Instructor's teaching method and common pitfalls
Separate a question from a claim of causation and make the measurement unit explicit (milliseconds).
Common trap / interpretation warning
Four simulated trials do not support general population conclusions.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
Distinguish the outcome variable (what is measured), predictor (a possible explanation), units, and a potential confounder (a factor associated with both). Fictional observational values are useful for teaching code but cannot establish a real causal claim.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Write a fictional research question and store it as a text value.
# question <-
# Step 2. Create a short numeric vector of fictional reaction times.
# rt_demo <- c(
# Step 3. Print a small data frame with trial numbers and reaction times.
# print(data.frame(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Assign the computed result to a named R object.
question <- "Does sleep predict response time?" # A question is not a causal conclusion.
# NOTE: Define an illustrative vector of fictional reaction times.
rt_demo <- c(620, 610, 590, 605) # Fictional reaction times in milliseconds.
# NOTE: Show the result in the Console (or display a ggplot object).
print(data.frame(trial=seq_along(rt_demo), rt_ms=rt_demo))Expected output, excerpts and validation checks
trial rt_ms
1 1 620
2 2 610
3 3 590
4 4 605Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
Data wrangling, joins and paired differences
Original Teacher's Kit — Week 2: teaching notes, alternative demonstration and line-by-line R analysis
Data wrangling and paired change
Perform a two-key join, isolate pre/post occasions, match individuals and summarize within-person change.
Expected output and interpretation
There are 22 measurement rows and 12 participant records. Ten have both occasions, yielding 10 matched pairs. Mean paired AHI change is +2.9 points; group A +3 and B +2.75 (entirely fictional).
Live demonstration
Ask why joining by id alone is not universally safe; have the student verify occasion codes 0/1 before analysis.
R script: line-by-line explanation
The table shows executable lines from the openly published, original solution. Continuation lines of multi-line calls are explained separately.
| R code | What exactly happens? |
|---|---|
01participants <- read.csv("data/participants.csv") | Reads participant identifiers and group labels; uniqueness of id alone should not be assumed. |
02scores <- read.csv("data/scores.csv") | Reads repeated observations: each row can represent a person–occasion record. |
03stopifnot(all(scores$occasion %in% c(0,1))) | %in% checks that occasion values are only 0 or 1, as defined in this fabricated dataset. |
04combined <- merge(scores,participants,by=c("id","intervention")) | merge(...,by=c('id','intervention')) requires both keys to match, preventing cross-group joins. |
05before <- combined[combined$occasion==0,c("id","intervention","ahiTotal")] | Selects occasion==0 rows and three columns; before the comma filters rows, after it selects columns. |
06after <- combined[combined$occasion==1,c("id","intervention","ahiTotal")] | Separates the occasion==1 post observations into a data frame. |
07names(before)[3] <- "pre" | Renames the third column from ahiTotal to pre without changing its values. |
08names(after)[3] <- "post" | Renames the post measurement column to post, avoiding ambiguous names after merging. |
09paired <- merge(before,after,by=c("id","intervention")) | Retains only id+intervention keys with both pre and post values; missing follow-up records are excluded. |
10paired$delta <- paired$post-paired$pre | post-pre is within-person change; a positive difference indicates an increase, not a causal effect. |
11print(paired) | Prints the matched table so the instructor can inspect whether each row corresponds to a single person. |
12print(nrow(paired)) | nrow(paired) counts complete pairs, here 10 rather than all participants. |
13print(mean(paired$delta)) | Averages within-person differences; the fictional result is +2.9. |
14print(aggregate(delta~intervention,paired,mean)) | Summarizes average change by group; these labels are not randomized conditions. |
15stopifnot(nrow(paired)==10L,nrow(combined)==22L) | Asserts 22 raw observation rows and 10 matched pairs; the test must change if input data change. |
16cat("W2 PASS: matched 10/12 synthetic records\n") | cat() prints a synthetic-data check message, not evidence of research validity. |
Likely misconception
The original source codebook says occasion 0=pre, 1=post, 2=follow-up, despite conflicting practical hints. Difference of two unpaired means is not the same analysis as paired differences; no causal claim follows.
Exit check
Why did we use two join keys? Why did only 10 of 12 records form pairs? Could missing follow-up data bias the comparison?
W2-M01 Packages and importing CSV
MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part A tasks 1–2. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 4 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- read.csv() Expanded reference ↗
- Read a comma-separated file into a data frame. Check argument names and data types before running the code.
read.csv("data/file.csv", stringsAsFactors=FALSE) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - nrow() Expanded reference ↗
- Count the number of rows in a table. Check argument names and data types before running the code.
nrow(data)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
read.csv() loads rows and columns from disk into R. stringsAsFactors=FALSE keeps text as text; the working directory determines where the relative data/ path begins.
CSV files are plain-text tables until read.csv() imports them as data frames. Relative paths, such as data/participant-info.csv, are resolved from getwd(), not necessarily the script’s location. Check nrow(), names() and head() after importing. The open package uses synthetic records.
Step-by-step classroom instructions
- Import data/participant-info.csv as the data frame pinfo.
- Import data/ahi-cesd.csv as the data frame responses.
- Print the participant and response row counts using nrow().
Masterclass learning goals
Learning goal: Read participant-info.csv and ahi-cesd.csv as pinfo and responses.
Concept: Packages, relative paths and importing CSV files as data frames.
Original task checklist
Task instructions — what the student must do
- Import data/participant-info.csv as the data frame pinfo.
- Import data/ahi-cesd.csv as the data frame responses.
- Print the participant and response row counts using nrow().
Instructor's teaching method and common pitfalls
Identify each file’s unit of observation before joining: one participant-level table versus repeated measurements.
Common trap / interpretation warning
Extract the full package and keep the data/ directory adjacent to the script.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
CSV files are plain-text tables until read.csv() imports them as data frames. Relative paths, such as data/participant-info.csv, are resolved from getwd(), not necessarily the script’s location. Check nrow(), names() and head() after importing. The open package uses synthetic records.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Import data/participant-info.csv as the data frame pinfo.
# pinfo <- read.csv(
# Step 2. Import data/ahi-cesd.csv as the data frame responses.
# responses <- read.csv(
# Step 3. Print the participant and response row counts using nrow().
# print(c(n_participants=Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# Run install.packages("tidyverse") ONCE in Console if not installed.
# library(tidyverse) loads dplyr, tidyr, ggplot2 etc. from your R library.
# NOTE: Read an input CSV into a data frame; check the working directory.
pinfo <- read.csv("data/participant-info.csv", stringsAsFactors=FALSE)
# NOTE: Read an input CSV into a data frame; check the working directory.
responses <- read.csv("data/ahi-cesd.csv", stringsAsFactors=FALSE)
# NOTE: Show the result in the Console (or display a ggplot object).
print(c(n_participants=nrow(pinfo), n_responses=nrow(responses)))Expected output, excerpts and validation checks
n_participants n_responses
# Numeric counts depend on the included fictional public CSV files.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W2-M02 Join by a compound key
MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part A task 3. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 6 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- inner_join() Expanded reference ↗
- Keep and combine rows whose keys match in both tables. Check join keys, missing matches and possible duplicate-key expansion.
dplyr::inner_join(x, y, by="id") - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - nrow() Expanded reference ↗
- Count the number of rows in a table. Check argument names and data types before running the code.
nrow(data) - n_distinct() Expanded reference ↗
- Count distinct values in a vector. Check argument names and data types before running the code.
dplyr::n_distinct(x) - stopifnot() Expanded reference ↗
- Stop execution with an error if a logical condition is not true. Check argument names and data types before running the code.
stopifnot(condition)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
A compound join key uses BOTH id and intervention to associate each measurement with the correct participant information. A join can silently lose rows or multiply records if keys are wrong.
A join matches rows using agreed key columns; here both participant id and intervention matter. Check uniqueness on each side before joining: repeated keys may create an unexpected many-to-many expansion. A successful join should be checked by both row count and distinct IDs.
Step-by-step classroom instructions
- Join participant information and responses by both id and intervention.
- Print the row count and number of distinct participants after the join.
Masterclass learning goals
Learning goal: Join demographics and repeated responses by id AND intervention.
Concept: Joining tables on the correct compound key and checking cardinality.
Original task checklist
Task instructions — what the student must do
- Join participant information and responses by both id and intervention.
- Print the row count and number of distinct participants after the join.
Instructor's teaching method and common pitfalls
Ask why joining only on intervention would create many-to-many matches, and how to check uniqueness of the participant table.
Common trap / interpretation warning
The nrow inequality catches row explosions but does not prove that all records matched correctly.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
A join matches rows using agreed key columns; here both participant id and intervention matter. Check uniqueness on each side before joining: repeated keys may create an unexpected many-to-many expansion. A successful join should be checked by both row count and distinct IDs.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Join participant information and responses by both id and intervention.
# all_data <- dplyr::inner_join(
# Step 2. Print the row count and number of distinct participants after the join.
# print(c(rows=Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Join matching records using the specified key columns.
all_data <- dplyr::inner_join(pinfo, responses, by=c("id","intervention"))
# NOTE: Show the result in the Console (or display a ggplot object).
print(c(rows=nrow(all_data), unique_ids=dplyr::n_distinct(all_data$id)))
# NOTE: Assert that a data-quality or numerical check is true; stop on failure.
stopifnot(nrow(all_data) <= nrow(responses)) # Key matching must not explode rows.Expected output, excerpts and validation checks
rows unique_ids
# Two named counts; values depend on the loaded public datasets.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W2-M03 select(): columns
MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part B select. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 3 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- select() Expanded reference ↗
- Choose or rename columns in a data frame. Check argument names and data types before running the code.
dplyr::select(data, col1, col2) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - names() Expanded reference ↗
- Get or assign column or element names. Check argument names and data types before running the code.
names(data)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
select() controls WHICH variables are retained, not which observations. Keeping a small, explicitly named set makes later calculations easier to inspect.
select() chooses variables (columns), while filter() chooses observations (rows). Explicitly naming columns documents the analysis plan and reduces accidental use of unrelated measures. Verify the selection with names() and preserve the intended data types.
Step-by-step classroom instructions
- Select the required analysis columns without removing any rows.
- Print the resulting column names to verify your selection.
Masterclass learning goals
Learning goal: Select nine requested columns.
Concept: Selecting columns rather than filtering rows.
Original task checklist
Task instructions — what the student must do
- Select the required analysis columns without removing any rows.
- Print the resulting column names to verify your selection.
Instructor's teaching method and common pitfalls
Ask learners to explain why the output has nine names but potentially many rows.
Common trap / interpretation warning
select() preserves row count and existing order unless other operations are added.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
select() chooses variables (columns), while filter() chooses observations (rows). Explicitly naming columns documents the analysis plan and reduces accidental use of unrelated measures. Verify the selection with names() and preserve the intended data types.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Select the required analysis columns without removing any rows.
# selected_vars <- dplyr::select(
# Step 2. Print the resulting column names to verify your selection.
# print(names(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Choose or rename variables; this does not filter rows.
selected_vars <- dplyr::select(all_data, id, intervention, ahiTotal, cesdTotal,
# NOTE: Continue this R expression with its arguments, values or formatting.
sex, age, educ, income, occasion)
# NOTE: Show the result in the Console (or display a ggplot object).
print(names(selected_vars)) # Exactly nine specified columns.Expected output, excerpts and validation checks
[1] "id" "intervention" "ahiTotal" "cesdTotal" "sex"
[6] "age" "educ" "income" "occasion"Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W2-M04 filter(): observations and a source correction
MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part B filter, compared with code-book.pdf. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 5 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- filter() Expanded reference ↗
- Keep rows satisfying the specified logical condition. Rows with an NA condition are not retained.
dplyr::filter(data, condition) - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - table() Expanded reference ↗
- Count frequencies of unique values. Check argument names and data types before running the code.
table(x) - %in% Expanded reference ↗
- Return TRUE when each element belongs to the specified set of values.
x %in% c(0,1)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
filter() controls WHICH rows are retained using a logical predicate. The verified codebook defines occasion 0 as pretest, 1 as posttest, and 2 as the one-week follow-up.
The uploaded codebook gives occasion=0 as baseline, 1 as posttest, and 2 as one-week follow-up. An inconsistent worksheet shortcut must not override the codebook. The expression occasion %in% c(0,1) keeps both desired times. Verify actual frequency counts with table().
Step-by-step classroom instructions
- Keep only observations at baseline (occasion 0) and posttest (occasion 1).
- Count and print observations for each occasion to check the filter.
Masterclass learning goals
Learning goal: Filter baseline (0) and posttest (1) after reading codebook.
Concept: Filtering rows and interpreting the measurement-time codebook.
Original task checklist
Task instructions — what the student must do
- Keep only observations at baseline (occasion 0) and posttest (occasion 1).
- Count and print observations for each occasion to check the filter.
Instructor's teaching method and common pitfalls
Have learners explain %in% c(0,1) as the equivalent of occasion == 0 | occasion == 1.
Common trap / interpretation warning
Do not use 1/2 as pre/post: the original worksheet shortcut contradicts the codebook.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
The uploaded codebook gives occasion=0 as baseline, 1 as posttest, and 2 as one-week follow-up. An inconsistent worksheet shortcut must not override the codebook. The expression occasion %in% c(0,1) keeps both desired times. Verify actual frequency counts with table().
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Keep only observations at baseline (occasion 0) and posttest (occasion 1).
# pre_post <- dplyr::filter(
# Step 2. Count and print observations for each occasion to check the filter.
# print(table(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# MOODLE CORRECTION: worksheet says 1/2 are pre/post; codebook is authoritative:
# occasion 0 = pretest; 1 = posttest; 2 = one-week follow-up.
# NOTE: Retain only observations that meet the filter condition.
pre_post <- dplyr::filter(selected_vars, occasion %in% c(0,1))
# NOTE: Show the result in the Console (or display a ggplot object).
print(table(pre_post$occasion)) # Inspect sample size/attrition per occasion.Expected output, excerpts and validation checks
0 1
# Counts for baseline and posttest; public fictional data values vary.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W2-M05 arrange(): rows
MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part B arrange. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 4 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- arrange() Expanded reference ↗
- Sort rows by one or more columns. Check argument names and data types before running the code.
dplyr::arrange(data, col) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - head() Expanded reference ↗
- Show the first n elements or rows. Check argument names and data types before running the code.
head(x, n=6) - select() Expanded reference ↗
- Choose or rename columns in a data frame. Check argument names and data types before running the code.
dplyr::select(data, col1, col2)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
arrange() sorts observations by a column but does not change the values or select a subset. It is especially useful for checking extreme observations.
arrange(x, ahiTotal) sorts rows in ascending AHI order; desc(ahiTotal) reverses the direction. Sorting changes only order, not the number of observations or their measured values. Use head() to verify the smallest or largest entries.
Step-by-step classroom instructions
- Sort the selected observations by ahiTotal from low to high.
- Print the first rows of the sorted data frame.
Masterclass learning goals
Learning goal: Sort AHI scores ascending.
Concept: Ordering observations without changing their values.
Original task checklist
Task instructions — what the student must do
- Sort the selected observations by ahiTotal from low to high.
- Print the first rows of the sorted data frame.
Instructor's teaching method and common pitfalls
Compare ascending arrange(..., ahiTotal) with arrange(..., desc(ahiTotal)).
Common trap / interpretation warning
Sorting and filtering are different: arrange() retains all input rows.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
arrange(x, ahiTotal) sorts rows in ascending AHI order; desc(ahiTotal) reverses the direction. Sorting changes only order, not the number of observations or their measured values. Use head() to verify the smallest or largest entries.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Sort the selected observations by ahiTotal from low to high.
# pre_post_asc <- dplyr::arrange(
# Step 2. Print the first rows of the sorted data frame.
# print(head(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Sort rows by the given variable without changing their values.
pre_post_asc <- dplyr::arrange(pre_post, ahiTotal)
# NOTE: Show the result in the Console (or display a ggplot object).
print(head(dplyr::select(pre_post_asc, id, occasion, ahiTotal)))Expected output, excerpts and validation checks
id occasion ahiTotal
# First six rows after ascending sorting; exact values are data-dependent.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W2-M06 summarise(): overall means
MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part B summarise. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 4 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- summarise() Expanded reference ↗
- Produce summary statistics for the whole table or each group. Check argument names and data types before running the code.
dplyr::summarise(data, metric=mean(x)) - n() Expanded reference ↗
- Return the number of rows in the active dplyr group. Check argument names and data types before running the code.
dplyr::n() - mean() Expanded reference ↗
- Calculate an arithmetic average. Use na.rm=TRUE to omit missing values explicitly.
mean(x, na.rm=FALSE) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
summarise() collapses a table to aggregate statistics. n() counts rows; mean(..., na.rm=TRUE) ignores missing values for each respective mean.
The arithmetic mean is the sum of available measurements divided by the number of non-missing values included. na.rm=TRUE removes NA values from the calculation; it does not replace them with zero. Different variables may therefore have different effective sample sizes.
Step-by-step classroom instructions
- Calculate overall average AHI and CES-D scores in one summary row.
- Print the completed overall summary table.
Masterclass learning goals
Learning goal: Make one-row AHI and CES-D mean summary.
Concept: Descriptive summaries and explicit missing-value handling.
Original task checklist
Task instructions — what the student must do
- Calculate overall average AHI and CES-D scores in one summary row.
- Print the completed overall summary table.
Instructor's teaching method and common pitfalls
Ask whether n() equals the number of NON-MISSING AHI values; discuss why the two could differ.
Common trap / interpretation warning
n() counts all rows, including those with an NA in a measured variable.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
The arithmetic mean is the sum of available measurements divided by the number of non-missing values included. na.rm=TRUE removes NA values from the calculation; it does not replace them with zero. Different variables may therefore have different effective sample sizes.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Calculate overall average AHI and CES-D scores in one summary row.
# overall_summary <- dplyr::summarise(
# Step 2. Print the completed overall summary table.
# print(overall_summaryInstructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Reduce each group to its aggregate statistics.
overall_summary <- dplyr::summarise(pre_post,
# NOTE: Compute an arithmetic mean of the selected numbers.
n=dplyr::n(), mean_ahi=mean(ahiTotal,na.rm=TRUE),
# NOTE: Compute an arithmetic mean of the selected numbers.
mean_cesd=mean(cesdTotal,na.rm=TRUE))
# NOTE: Show the result in the Console (or display a ggplot object).
print(overall_summary)Expected output, excerpts and validation checks
n mean_ahi mean_cesd
# One row with three summary columns; numbers depend on input CSVs.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W2-M07 group_by(): distinct occasion summaries
MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part B group_by. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 6 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- group_by() Expanded reference ↗
- Set the grouping keys used by later operations. Remember to inspect or remove grouping after grouped summaries.
dplyr::group_by(data, group) - summarise() Expanded reference ↗
- Produce summary statistics for the whole table or each group. Check argument names and data types before running the code.
dplyr::summarise(data, metric=mean(x)) - n() Expanded reference ↗
- Return the number of rows in the active dplyr group. Check argument names and data types before running the code.
dplyr::n() - mean() Expanded reference ↗
- Calculate an arithmetic average. Use na.rm=TRUE to omit missing values explicitly.
mean(x, na.rm=FALSE) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - |> Expanded reference ↗
- Pass the preceding result to the next function call.
data |> function()
Concepts, learning goals and student instructions
What this teaches — concept breakdown
group_by(occasion) changes the unit of summarisation to a measurement occasion. A grouped mean is not necessarily the mean within-person change because different people can appear at each time.
group_by(occasion) controls how a later summarise() operates: one summary row per measurement occasion. Counts at baseline and posttest need not be equal. A difference between group means across occasions is not, by itself, a within-person change or a treatment effect.
Step-by-step classroom instructions
- Start a pipe to summarise the sorted pre/post observations.
- Group the piped observations by occasion.
- Compute sample sizes and means separately for each occasion.
Masterclass learning goals
Learning goal: Summarise each measurement occasion separately.
Concept: Grouped statistics and different sample sizes across occasions.
Original task checklist
Task instructions — what the student must do
- Start a pipe to summarise the sorted pre/post observations.
- Group the piped observations by occasion.
- Compute sample sizes and means separately for each occasion.
Instructor's teaching method and common pitfalls
Contrast mean(post) - mean(pre) across two unmatched samples with mean(post_i - pre_i) on complete pairs.
Common trap / interpretation warning
If a score contains missing values, mean() without na.rm=TRUE may return NA.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
group_by(occasion) controls how a later summarise() operates: one summary row per measurement occasion. Counts at baseline and posttest need not be equal. A difference between group means across occasions is not, by itself, a within-person change or a treatment effect.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Start a pipe to summarise the sorted pre/post observations.
# occasion_summary <- pre_post_asc |>
# Step 2. Group the piped observations by occasion.
# dplyr::group_by(
# Step 3. Compute sample sizes and means separately for each occasion.
# dplyr::summarise(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Assign the computed result to a named R object.
occasion_summary <- pre_post_asc |>
# NOTE: Define the groups to be summarised independently.
dplyr::group_by(occasion) |>
# NOTE: Reduce each group to its aggregate statistics.
dplyr::summarise(n=dplyr::n(), mean_ahi=mean(ahiTotal),
# NOTE: Compute an arithmetic mean of the selected numbers.
mean_cesd=mean(cesdTotal), .groups="drop")
# NOTE: Show the result in the Console (or display a ggplot object).
print(occasion_summary)Expected output, excerpts and validation checks
occasion n mean_ahi mean_cesd
# One summary row per occasion (0 and 1).Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W2-M08 mutate(): new column and scale caution
MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part B mutate. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 4 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- mutate() Expanded reference ↗
- Create or alter one or more columns. Check argument names and data types before running the code.
dplyr::mutate(data, new=x+y) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - head() Expanded reference ↗
- Show the first n elements or rows. Check argument names and data types before running the code.
head(x, n=6) - select() Expanded reference ↗
- Choose or rename columns in a data frame. Check argument names and data types before running the code.
dplyr::select(data, col1, col2)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
mutate() adds a derived column while keeping the observation rows. Subtracting two different scale totals is mathematically possible but may have no validated clinical meaning.
mutate() creates a new column computed from existing columns. The numerical expression cesdTotal - ahiTotal may be useful to demonstrate syntax, but a difference between two unrelated psychometric scales is not automatically a meaningful clinical “sadness” measure.
Step-by-step classroom instructions
- Create a new sadness column by subtracting ahiTotal from cesdTotal.
- Print the first rows of the new variable alongside its inputs.
Masterclass learning goals
Learning goal: Create sadness = cesdTotal - ahiTotal as a syntax exercise.
Concept: Creating derived columns; numerical differences versus validated scales.
Original task checklist
Task instructions — what the student must do
- Create a new sadness column by subtracting ahiTotal from cesdTotal.
- Print the first rows of the new variable alongside its inputs.
Instructor's teaching method and common pitfalls
Ask learners to calculate one row manually and explain why naming a value sadness does not make it a mental-health measure.
Common trap / interpretation warning
This 'sadness' variable is ONLY a syntax exercise; it is not a legitimate clinical index.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
mutate() creates a new column computed from existing columns. The numerical expression cesdTotal - ahiTotal may be useful to demonstrate syntax, but a difference between two unrelated psychometric scales is not automatically a meaningful clinical “sadness” measure.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Create a new sadness column by subtracting ahiTotal from cesdTotal.
# pre_post <- dplyr::mutate(
# Step 2. Print the first rows of the new variable alongside its inputs.
# print(head(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Create or recode columns while retaining row-level observations.
pre_post <- dplyr::mutate(pre_post, sadness=cesdTotal-ahiTotal)
# NOTE: Show the result in the Console (or display a ggplot object).
print(head(dplyr::select(pre_post, sadness, cesdTotal, ahiTotal)))
# DO NOT interpret "sadness" clinically: AHI/CES-D scales have different constructs/ranges.Expected output, excerpts and validation checks
sadness cesdTotal ahiTotal
# First six rows; sadness = cesdTotal - ahiTotal.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W2-M09 Recode sex using the codebook
MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part B recode, compared with code-book.pdf. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 5 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- mutate() Expanded reference ↗
- Create or alter one or more columns. Check argument names and data types before running the code.
dplyr::mutate(data, new=x+y) - factor() Expanded reference ↗
- Represent categorical values with ordered levels and labels. Incorrect levels or labels can reverse category meanings.
factor(x, levels=..., labels=...) - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - table() Expanded reference ↗
- Count frequencies of unique values. Check argument names and data types before running the code.
table(x)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
factor() maps numerical category codes to readable labels. The source codebook defines sex=1 as Female and sex=2 as Male, so the levels and labels must align.
The uploaded codebook specifies sex=1 for Female and sex=2 for Male. A reversed factor label silently inverts subgroup interpretations. Use factor(x, levels=c(1,2), labels=c("Female","Male")) and verify frequency counts after recoding.
Step-by-step classroom instructions
- Add a correctly labelled sex variable to the pre/post data frame.
- Use the codebook mapping 1 = Female and 2 = Male in factor().
Masterclass learning goals
Learning goal: Recode sex=1 Female, sex=2 Male correctly.
Concept: Categorical recoding using an authoritative codebook.
Original task checklist
Task instructions — what the student must do
- Add a correctly labelled sex variable to the pre/post data frame.
- Use the codebook mapping 1 = Female and 2 = Male in factor().
Instructor's teaching method and common pitfalls
Inspect table(..., useNA='ifany') and check that all source values map to their intended labels.
Common trap / interpretation warning
Reversing the codebook mappings would silently mislabel participants.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
The uploaded codebook specifies sex=1 for Female and sex=2 for Male. A reversed factor label silently inverts subgroup interpretations. Use factor(x, levels=c(1,2), labels=c("Female","Male")) and verify frequency counts after recoding.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Add a correctly labelled sex variable to the pre/post data frame.
# pre_post <- dplyr::mutate(
# Step 2. Use the codebook mapping 1 = Female and 2 = Male in factor().
# sex_label=factor(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# MOODLE CORRECTION: worksheet labels conflict with source codebook.
# Correct coding in code-book.pdf: 1=Female, 2=Male.
# NOTE: Create or recode columns while retaining row-level observations.
pre_post <- dplyr::mutate(pre_post,
# NOTE: Map numeric category codes to readable factor levels.
sex_label=factor(sex,levels=c(1,2),labels=c("Female","Male")))
# NOTE: Show the result in the Console (or display a ggplot object).
print(table(pre_post$sex_label, useNA="ifany"))Expected output, excerpts and validation checks
Female Male
# Category frequencies; an NA row appears if unmatched/missing values occur.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W2-E01 Additional: paired change and attrition
MOODLE SOURCE NOTE: ferdo Lab original extension. INDEPENDENT ADDITION (not an official Moodle task).
R functions and syntax reference · 9 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- filter() Expanded reference ↗
- Keep rows satisfying the specified logical condition. Rows with an NA condition are not retained.
dplyr::filter(data, condition) - select() Expanded reference ↗
- Choose or rename columns in a data frame. Check argument names and data types before running the code.
dplyr::select(data, col1, col2) - inner_join() Expanded reference ↗
- Keep and combine rows whose keys match in both tables. Check join keys, missing matches and possible duplicate-key expansion.
dplyr::inner_join(x, y, by="id") - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - mutate() Expanded reference ↗
- Create or alter one or more columns. Check argument names and data types before running the code.
dplyr::mutate(data, new=x+y) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - summarise() Expanded reference ↗
- Produce summary statistics for the whole table or each group. Check argument names and data types before running the code.
dplyr::summarise(data, metric=mean(x)) - n() Expanded reference ↗
- Return the number of rows in the active dplyr group. Check argument names and data types before running the code.
dplyr::n() - mean() Expanded reference ↗
- Calculate an arithmetic average. Use na.rm=TRUE to omit missing values explicitly.
mean(x, na.rm=FALSE)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
Pairing requires the SAME participant to have both a baseline (occasion 0) and posttest (occasion 1) measurement. inner_join retains matched pairs and mutate computes each individual's post-minus-pre change.
For paired change, match the same participant’s baseline and posttest values and calculate the difference within each matched pair. Subtracting the two unpaired occasion means is not generally equivalent. Missing follow-ups may introduce attrition and selection bias.
Step-by-step classroom instructions
- Filter baseline records for participants observed before the intervention.
- Filter posttest records for participants observed after the intervention.
- Join the two sets by participant and compute within-person change.
Masterclass learning goals
Learning goal: Contrast paired change with unpaired occasion means.
Concept: Within-person paired differences, missing pairs and selection bias.
Original task checklist
Task instructions — what the student must do
- Filter baseline records for participants observed before the intervention.
- Filter posttest records for participants observed after the intervention.
- Join the two sets by participant and compute within-person change.
Instructor's teaching method and common pitfalls
Emphasise that paired change is not the same as subtracting two unpaired occasion means; attrition can bias the matched subset.
Common trap / interpretation warning
Check uniqueness of (id, intervention, occasion); missing follow-ups and NA scores need explicit handling.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
For paired change, match the same participant’s baseline and posttest values and calculate the difference within each matched pair. Subtracting the two unpaired occasion means is not generally equivalent. Missing follow-ups may introduce attrition and selection bias.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Filter baseline records for participants observed before the intervention.
# paired_pre <- dplyr::filter(
# Step 2. Filter posttest records for participants observed after the intervention.
# paired_post <- dplyr::filter(
# Step 3. Join the two sets by participant and compute within-person change.
# paired_data <- dplyr::inner_join(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Keep baseline observations and preserve identifiers for later pairing.
paired_pre <- dplyr::filter(all_data, occasion==0) |>
# NOTE: Choose or rename variables; this does not filter rows.
dplyr::select(id,intervention,ahi_pre=ahiTotal)
# NOTE: Keep posttest observations and preserve identifiers for later pairing.
paired_post <- dplyr::filter(all_data, occasion==1) |>
# NOTE: Choose or rename variables; this does not filter rows.
dplyr::select(id,intervention,ahi_post=ahiTotal)
# NOTE: Join matching records using the specified key columns.
paired_data <- dplyr::inner_join(paired_pre,paired_post,by=c("id","intervention")) |>
# NOTE: Create or recode columns while retaining row-level observations.
dplyr::mutate(change_ahi=ahi_post-ahi_pre)
# NOTE: Show the result in the Console (or display a ggplot object).
print(dplyr::summarise(paired_data, paired_n=dplyr::n(), mean_change=mean(change_ahi)))Expected output, excerpts and validation checks
paired_n mean_change
# One row: count of matched pairs and their average ahi_post - ahi_pre.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
AQ-10 scoring and descriptive statistics
Original Teacher's Kit — Week 3: teaching notes, alternative demonstration and line-by-line R analysis
AQ-like scoring and summaries
Reshape wide responses to long format, join item-format and scoring lookups, then summarize binary item scores.
Expected output and interpretation
The toy data contain 8 × 10 = 80 responses. By ID S01–S08 the totals are 6, 4, 5, 4, 6, 3, 7, 4; mean = 4.875, sample SD ≈ 1.356. These are programming outputs, not clinical classifications.
Live demonstration
How does scoring differ for F and R item keys? Hand-score two responses before automating reshape and joins.
R script: line-by-line explanation
The table shows executable lines from the openly published, original solution. Continuation lines of multi-line calls are explained separately.
| R code | What exactly happens? |
|---|---|
01aq <- read.csv("data/aq10.csv",check.names=FALSE) | check.names=FALSE preserves Q1…Q10 names; in wide format each row is a participant. |
02formats <- read.csv("data/aq_formats.csv") | Reads the lookup that assigns F/R scoring directions to each item. |
03scoring <- read.csv("data/aq_scoring.csv") | Reads the second lookup mapping F/R plus Agree/Disagree to binary 0/1 scores. |
04items <- paste0("Q",1:10) | paste0('Q',1:10) constructs the column names Q1 through Q10. |
05long <- reshape(aq,varying=items,v.names="response", | reshape() begins converting ten question columns into one long response column while retaining identifiers. |
06timevar="question",times=items,direction="long") | timevar/times populate a question label Q1…Q10; direction='long' increases the row count. |
07rownames(long) <- NULL | Removes auto-generated row names; it does not erase participant IDs. |
08long <- merge(long,formats,by="question") | Joins by question to attach each item's F/R scoring direction to every response. |
09long$agrees <- grepl("Agree",long$response,fixed=TRUE) | grepl('Agree',response,fixed=TRUE) flags labels containing Agree; it assumes a controlled vocabulary. |
10long$response_kind <- ifelse(long$agrees,"Agree","Disagree") | ifelse() transforms the Boolean flag into the labels Agree and Disagree. |
11long <- merge(long,scoring,by=c("format","response_kind")) | The second merge attaches score using format + response_kind; inspect unmatched cases before trusting totals. |
12totals <- aggregate(score~id,long,sum) | aggregate(score~id,long,sum) adds the ten binary item scores per participant. |
13print(totals) | Prints IDs and calculated totals without assigning a clinical label. |
14print(mean(totals$score)) | Calculates the mean of the eight fictional totals. |
15print(sd(totals$score)) | sd() computes the sample standard deviation of the eight totals (n−1 denominator). |
16stopifnot(nrow(totals)==8L,all(totals$score>=0),all(totals$score<=10)) | Checks eight participants and totals within 0–10; also discuss validating 80 long rows and ten items per ID. |
17cat("W3 PASS: 8 original fictional AQ-like screening totals\n") | cat() prints a code-check message; it does not validate diagnostic accuracy. |
Likely misconception
grepl('Agree', ...) works only for the provided controlled response labels, not arbitrary free text. An educational AQ-like total is not a diagnosis.
Exit check
Why join the question format before the scoring table? If only 79 rather than 80 rows remain, which join needs checking?
W3-M01 Read AQ, formats, scoring
MOODLE SOURCE NOTE: wk3_practical_summarising_data (1).r · Part A task 1. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 4 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- read.csv() Expanded reference ↗
- Read a comma-separated file into a data frame. Check argument names and data types before running the code.
read.csv("data/file.csv", stringsAsFactors=FALSE) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - nrow() Expanded reference ↗
- Count the number of rows in a table. Check argument names and data types before running the code.
nrow(data)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
The AQ-10 practical stores questionnaire responses, item direction (forward/reverse) and scoring rules in three separate CSV files. Punctuation, case and spelling of response labels must agree across files.
AQ responses, question directions and scoring rules are stored in three files. The exact column spellings and key values must be checked before joining. The scoring table connects direction (forward/reverse) and the normalised response category to a 0 or 1 point.
Step-by-step classroom instructions
- Read the question-format lookup file from the data folder.
- Read the scoring-key lookup file from the data folder.
- Read the AQ questionnaire response table from the data folder.
Masterclass learning goals
Learning goal: Load Qformats, Scoring and AQ data.
Concept: Reading a questionnaire and the separate format/scoring lookups.
Original task checklist
Task instructions — what the student must do
- Read the question-format lookup file from the data folder.
- Read the scoring-key lookup file from the data folder.
- Read the AQ questionnaire response table from the data folder.
Instructor's teaching method and common pitfalls
Explain the different roles: AQ.csv holds participant responses; Qformats.csv maps questions to direction; Scoring.csv maps direction+response to 0/1.
Common trap / interpretation warning
The public data are fictional. Do not assume the original Moodle row counts are reproduced there.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
AQ responses, question directions and scoring rules are stored in three files. The exact column spellings and key values must be checked before joining. The scoring table connects direction (forward/reverse) and the normalised response category to a 0 or 1 point.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Read the question-format lookup file from the data folder.
# qformats <- read.csv(
# Step 2. Read the scoring-key lookup file from the data folder.
# scoring <- read.csv(
# Step 3. Read the AQ questionnaire response table from the data folder.
# aq_responses <- read.csv(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Read an input CSV into a data frame; check the working directory.
qformats <- read.csv("data/Qformats.csv", stringsAsFactors=FALSE)
# NOTE: Read an input CSV into a data frame; check the working directory.
scoring <- read.csv("data/Scoring.csv", stringsAsFactors=FALSE)
# NOTE: Read an input CSV into a data frame; check the working directory.
aq_responses <- read.csv("data/AQ.csv", stringsAsFactors=FALSE)
# NOTE: Show the result in the Console (or display a ggplot object).
print(c(participants=nrow(aq_responses),questions=nrow(qformats),rules=nrow(scoring)))Expected output, excerpts and validation checks
participants questions rules
# Three named counts; original private AQ source had 66 respondents and 10 items.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W3-M02 Wide-to-long pivot
MOODLE SOURCE NOTE: wk3_practical_summarising_data (1).r · Part A task 2. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 5 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- pivot_longer() Expanded reference ↗
- Reshape many columns into a smaller number of key/value columns. Check argument names and data types before running the code.
tidyr::pivot_longer(data, cols=..., names_to=..., values_to=...) - all_of() Expanded reference ↗
- Select columns identified by a character vector of names. Check argument names and data types before running the code.
dplyr::all_of(names) - paste0() Expanded reference ↗
- Join text and values without separators. Check argument names and data types before running the code.
paste0("Q", 1:10) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - dim() Expanded reference ↗
- Return dimensions, usually rows and columns. Check argument names and data types before running the code.
dim(x)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
pivot_longer() converts ten question columns (Q1 to Q10) into two fields, Question and Response, while repeating Id for every item. This changes shape, not substantive answers.
In wide format, each participant occupies one row and Q1–Q10 are separate columns. In long format, each participant-question response occupies one row, with Question and Response fields. This makes scoring and question-level grouping easier.
Step-by-step classroom instructions
- Start turning the wide AQ response table into a long table.
- Select the Q1 through Q10 columns for pivoting.
Masterclass learning goals
Learning goal: Convert Q1–Q10 into Question/Response rows.
Concept: Wide versus long data and person-by-question observations.
Original task checklist
Task instructions — what the student must do
- Start turning the wide AQ response table into a long table.
- Select the Q1 through Q10 columns for pivoting.
Instructor's teaching method and common pitfalls
Break down all_of(paste0('Q',1:10)), names_to and values_to; demonstrate how one participant becomes ten rows.
Common trap / interpretation warning
all_of() requires all Q1–Q10 columns to exist; verify column names and each participant's expected ten items.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
In wide format, each participant occupies one row and Q1–Q10 are separate columns. In long format, each participant-question response occupies one row, with Question and Response fields. This makes scoring and question-level grouping easier.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Start turning the wide AQ response table into a long table.
# aq_long <- tidyr::pivot_longer(
# Step 2. Select the Q1 through Q10 columns for pivoting.
# cols=dplyr::all_of(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Pivot Q1–Q10 columns into long-form question/response rows.
aq_long <- tidyr::pivot_longer(aq_responses,
# NOTE: Generate exact field names Q1 through Q10 without separators.
cols=dplyr::all_of(paste0("Q",1:10)),names_to="Question",values_to="Response")
# NOTE: Show the result in the Console (or display a ggplot object).
print(dim(aq_long)) # Real source: 66*10=660 rows; public demo differs.Expected output, excerpts and validation checks
[1] <participants × 10> <column count after pivot>
# In original private data, there were 66 × 10 = 660 long-form rows.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W3-M03 Join directions and exact scoring rules
MOODLE SOURCE NOTE: wk3_practical_summarising_data (1).r · Part A task 3. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 8 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- inner_join() Expanded reference ↗
- Keep and combine rows whose keys match in both tables. Check join keys, missing matches and possible duplicate-key expansion.
dplyr::inner_join(x, y, by="id") - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - stopifnot() Expanded reference ↗
- Stop execution with an error if a logical condition is not true. Check argument names and data types before running the code.
stopifnot(condition) - nrow() Expanded reference ↗
- Count the number of rows in a table. Check argument names and data types before running the code.
nrow(data) - anyNA() Expanded reference ↗
- Check whether an object contains missing values. Check argument names and data types before running the code.
anyNA(x) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - head() Expanded reference ↗
- Show the first n elements or rows. Check argument names and data types before running the code.
head(x, n=6) - select() Expanded reference ↗
- Choose or rename columns in a data frame. Check argument names and data types before running the code.
dplyr::select(data, col1, col2)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
The FIRST inner_join attaches forward/reverse question direction by Question. The SECOND join attaches the binary Score by the combined (QFormat, Response) lookup key.
Two matching steps are essential: first attach the forward/reverse direction to each question; then attach its numerical score using the direction and response. Failing to join on both required fields, or mismatching response text, can silently drop or duplicate records.
Step-by-step classroom instructions
- Join each long-format AQ response with its forward/reverse item direction.
- Join each response and direction combination to its 0/1 score.
Masterclass learning goals
Learning goal: Join each question to F/R and each response to its point value.
Concept: Two joins, reverse scoring and exact response-string matching.
Original task checklist
Task instructions — what the student must do
- Join each long-format AQ response with its forward/reverse item direction.
- Join each response and direction combination to its 0/1 score.
Instructor's teaching method and common pitfalls
Explain why response text alone is insufficient: the same response can receive different points depending on item direction.
Common trap / interpretation warning
inner_join can drop unmatched answers; equal row counts alone do not prove one-to-one matching.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
Two matching steps are essential: first attach the forward/reverse direction to each question; then attach its numerical score using the direction and response. Failing to join on both required fields, or mismatching response text, can silently drop or duplicate records.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Join each long-format AQ response with its forward/reverse item direction.
# aq_with_format <- dplyr::inner_join(
# Step 2. Join each response and direction combination to its 0/1 score.
# aq_scored <- dplyr::inner_join(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Join matching records using the specified key columns.
aq_with_format <- dplyr::inner_join(aq_long,qformats,by="Question")
# NOTE: Join matching records using the specified key columns.
aq_scored <- dplyr::inner_join(aq_with_format,scoring,by=c("QFormat","Response"))
# NOTE: Assert that a data-quality or numerical check is true; stop on failure.
stopifnot(nrow(aq_scored)==nrow(aq_long), !anyNA(aq_scored$Score))
# NOTE: Show the result in the Console (or display a ggplot object).
print(head(dplyr::select(aq_scored,Id,Question,Response,QFormat,Score)))Expected output, excerpts and validation checks
Id Question Response QFormat Score
# First six matched response rows, each with a binary Score (0 or 1).Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W3-M04 Participant total AQ score
MOODLE SOURCE NOTE: wk3_practical_summarising_data (1).r · Part A task 4. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 7 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- group_by() Expanded reference ↗
- Set the grouping keys used by later operations. Remember to inspect or remove grouping after grouped summaries.
dplyr::group_by(data, group) - summarise() Expanded reference ↗
- Produce summary statistics for the whole table or each group. Check argument names and data types before running the code.
dplyr::summarise(data, metric=mean(x)) - sum() Expanded reference ↗
- Add numeric values; optionally ignore missing values. Check argument names and data types before running the code.
sum(x, na.rm=FALSE) - stopifnot() Expanded reference ↗
- Stop execution with an error if a logical condition is not true. Check argument names and data types before running the code.
stopifnot(condition) - all() Expanded reference ↗
- Return TRUE only if every tested value is TRUE. Check argument names and data types before running the code.
all(logical) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - head() Expanded reference ↗
- Show the first n elements or rows. Check argument names and data types before running the code.
head(x, n=6)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
group_by(Id) makes each participant a separate calculation group. summarise(AQTotal=sum(Score)) adds the ten binary item scores and returns one row per respondent; .groups='drop' clears grouping.
group_by(id) ensures a sum is computed for each respondent rather than over the entire data set. The AQ-10 contains ten binary items, so a complete total has a theoretical range of 0–10. Count missing or unmatched item scores before interpreting totals.
Step-by-step classroom instructions
- Begin a pipe that calculates a total AQ-10 score for each participant.
- Group the scored questionnaire rows by participant ID.
- Sum the scored items separately for each participant.
Masterclass learning goals
Learning goal: Sum ten 0/1 items per participant.
Concept: Participant-level grouping and summing binary questionnaire items.
Original task checklist
Task instructions — what the student must do
- Begin a pipe that calculates a total AQ-10 score for each participant.
- Group the scored questionnaire rows by participant ID.
- Sum the scored items separately for each participant.
Instructor's teaching method and common pitfalls
Explain >=, <=, &, all() and stopifnot(). The range check is necessary but not sufficient to confirm ten valid scored answers.
Common trap / interpretation warning
A total within 0–10 may still come from fewer than ten scored questions. Check item counts per Id.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
group_by(id) ensures a sum is computed for each respondent rather than over the entire data set. The AQ-10 contains ten binary items, so a complete total has a theoretical range of 0–10. Count missing or unmatched item scores before interpreting totals.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Begin a pipe that calculates a total AQ-10 score for each participant.
# aq_scores <- aq_scored |>
# Step 2. Group the scored questionnaire rows by participant ID.
# dplyr::group_by(
# Step 3. Sum the scored items separately for each participant.
# dplyr::summarise(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Compute one AQ-10 total for each participant.
aq_scores <- aq_scored |>
# NOTE: Define the groups to be summarised independently.
dplyr::group_by(Id) |>
# NOTE: Reduce each group to its aggregate statistics.
dplyr::summarise(AQTotal=sum(Score),.groups="drop")
# NOTE: Assert that a data-quality or numerical check is true; stop on failure.
stopifnot(all(aq_scores$AQTotal >= 0 & aq_scores$AQTotal <= 10))
# NOTE: Show the result in the Console (or display a ggplot object).
print(head(aq_scores))Expected output, excerpts and validation checks
Id AQTotal
# First six participants with integer totals from 0 to 10.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W3-M05 Pipe version of a complete workflow
MOODLE SOURCE NOTE: wk3_practical_summarising_data (1).r · Part B pipe. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 11 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- pivot_longer() Expanded reference ↗
- Reshape many columns into a smaller number of key/value columns. Check argument names and data types before running the code.
tidyr::pivot_longer(data, cols=..., names_to=..., values_to=...) - all_of() Expanded reference ↗
- Select columns identified by a character vector of names. Check argument names and data types before running the code.
dplyr::all_of(names) - paste0() Expanded reference ↗
- Join text and values without separators. Check argument names and data types before running the code.
paste0("Q", 1:10) - inner_join() Expanded reference ↗
- Keep and combine rows whose keys match in both tables. Check join keys, missing matches and possible duplicate-key expansion.
dplyr::inner_join(x, y, by="id") - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - group_by() Expanded reference ↗
- Set the grouping keys used by later operations. Remember to inspect or remove grouping after grouped summaries.
dplyr::group_by(data, group) - summarise() Expanded reference ↗
- Produce summary statistics for the whole table or each group. Check argument names and data types before running the code.
dplyr::summarise(data, metric=mean(x)) - sum() Expanded reference ↗
- Add numeric values; optionally ignore missing values. Check argument names and data types before running the code.
sum(x, na.rm=FALSE) - stopifnot() Expanded reference ↗
- Stop execution with an error if a logical condition is not true. Check argument names and data types before running the code.
stopifnot(condition) - identical() Expanded reference ↗
- Test strict equality, including data types and attributes. Check argument names and data types before running the code.
identical(x, y) - |> Expanded reference ↗
- Compose data-processing steps in readable left-to-right order.
data |> transform()
Concepts, learning goals and student instructions
What this teaches — concept breakdown
The pipe chains the entire transformation: wide-to-long → join item direction → join scoring key → group by participant → sum item scores. It should reproduce the same totals as the separated steps.
The pipe operator |> passes the output of one transformation into the next. A long pipeline should reproduce the same participant totals as separate intermediate objects. Compare sorted scores for equality and debug each transformation stage if results disagree.
Step-by-step classroom instructions
- Start a single piped workflow using the original AQ response table.
- Reshape Q1–Q10 from wide to long format in the pipeline.
- Join the reshaped rows to the question format key, then continue scoring.
Masterclass learning goals
Learning goal: Recreate scoring through a chain of operations.
Concept: Pipes, function composition and equivalent scoring workflows.
Original task checklist
Task instructions — what the student must do
- Start a single piped workflow using the original AQ response table.
- Reshape Q1–Q10 from wide to long format in the pipeline.
- Join the reshaped rows to the question format key, then continue scoring.
Instructor's teaching method and common pitfalls
Use identical(aq_scores, aq_pipe) to test exact equality; isolate stages if it fails.
Common trap / interpretation warning
identical() checks classes, row order and attributes as well as values; equivalent data can sometimes differ in attributes.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
The pipe operator |> passes the output of one transformation into the next. A long pipeline should reproduce the same participant totals as separate intermediate objects. Compare sorted scores for equality and debug each transformation stage if results disagree.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Start a single piped workflow using the original AQ response table.
# aq_pipe <- aq_responses |>
# Step 2. Reshape Q1–Q10 from wide to long format in the pipeline.
# tidyr::pivot_longer(
# Step 3. Join the reshaped rows to the question format key, then continue scoring.
# dplyr::inner_join(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Perform the whole AQ workflow through one chained pipeline.
aq_pipe <- aq_responses |>
# NOTE: Pivot Q1–Q10 columns into long-form question/response rows.
tidyr::pivot_longer(cols=dplyr::all_of(paste0("Q",1:10)),
# NOTE: Continue this R expression with its arguments, values or formatting.
names_to="Question",values_to="Response") |>
# NOTE: Join matching records using the specified key columns.
dplyr::inner_join(qformats,by="Question") |>
# NOTE: Join matching records using the specified key columns.
dplyr::inner_join(scoring,by=c("QFormat","Response")) |>
# NOTE: Define the groups to be summarised independently.
dplyr::group_by(Id) |>
# NOTE: Reduce each group to its aggregate statistics.
dplyr::summarise(AQTotal=sum(Score),.groups="drop")
# NOTE: Assert that a data-quality or numerical check is true; stop on failure.
stopifnot(identical(aq_scores,aq_pipe)) # Native |> parallels tidyverse %>% for these operations.Expected output, excerpts and validation checks
# No printed output when stopifnot(identical(...)) passes.
# If it fails, R stops with an error.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W3-M06 Descriptives, cut-off and counts
MOODLE SOURCE NOTE: wk3_practical_summarising_data (1).r · Part C tasks 1–3. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 9 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- summarise() Expanded reference ↗
- Produce summary statistics for the whole table or each group. Check argument names and data types before running the code.
dplyr::summarise(data, metric=mean(x)) - n() Expanded reference ↗
- Return the number of rows in the active dplyr group. Check argument names and data types before running the code.
dplyr::n() - mean() Expanded reference ↗
- Calculate an arithmetic average. Use na.rm=TRUE to omit missing values explicitly.
mean(x, na.rm=FALSE) - sd() Expanded reference ↗
- Calculate the sample standard deviation. With the default sample definition, SD uses n−1 in the denominator.
sd(x) - min() Expanded reference ↗
- Return the smallest value. Check argument names and data types before running the code.
min(x, na.rm=FALSE) - max() Expanded reference ↗
- Return the largest value. Check argument names and data types before running the code.
max(x, na.rm=FALSE) - sum() Expanded reference ↗
- Add numeric values; optionally ignore missing values. Check argument names and data types before running the code.
sum(x, na.rm=FALSE) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - filter() Expanded reference ↗
- Keep rows satisfying the specified logical condition. Rows with an NA condition are not retained.
dplyr::filter(data, condition)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
mean and sd describe the distribution of participants' summed AQ scores. AQTotal > 6 is a screening-threshold count, not a diagnosis.
The mean describes central tendency and SD describes participant-to-participant dispersion. An illustrative threshold above 6 is a screening criterion, not a diagnosis. AQ-10 is discrete and bounded; do not assume it has a normal distribution just because mean and SD are reported.
Step-by-step classroom instructions
- Calculate the mean, standard deviation and range of AQ totals.
- Print the resulting descriptive summary.
Masterclass learning goals
Learning goal: Compute mean/SD/range; list people over six.
Concept: Means, standard deviations, scores and screening thresholds.
Original task checklist
Task instructions — what the student must do
- Calculate the mean, standard deviation and range of AQ totals.
- Print the resulting descriptive summary.
Instructor's teaching method and common pitfalls
Distinguish the number of people from the mean number of points; compare SD to the observed min/max.
Common trap / interpretation warning
A questionnaire screening threshold must not be interpreted as a clinical diagnostic finding.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
The mean describes central tendency and SD describes participant-to-participant dispersion. An illustrative threshold above 6 is a screening criterion, not a diagnosis. AQ-10 is discrete and bounded; do not assume it has a normal distribution just because mean and SD are reported.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Calculate the mean, standard deviation and range of AQ totals.
# aq_summary <- dplyr::summarise(
# Step 2. Print the resulting descriptive summary.
# print(aq_summaryInstructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Reduce each group to its aggregate statistics.
aq_summary <- dplyr::summarise(aq_scores,
# NOTE: Compute an arithmetic mean of the selected numbers.
n=dplyr::n(), mean=mean(AQTotal), sd=sd(AQTotal),
# NOTE: Continue this R expression with its arguments, values or formatting.
min=min(AQTotal), max=max(AQTotal), above6=sum(AQTotal>6))
# NOTE: Show the result in the Console (or display a ggplot object).
print(aq_summary)
# NOTE: Show the result in the Console (or display a ggplot object).
print(dplyr::filter(aq_scores,AQTotal>6))Expected output, excerpts and validation checks
n mean sd min max above6
# One summary row; followed by rows with AQTotal > 6.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W3-M07 AQ frequency histogram
MOODLE SOURCE NOTE: wk3_practical_summarising_data (1).r · Part C final histogram. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 7 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- ggplot() Expanded reference ↗
- Start a layered grammar-of-graphics plot. Check argument names and data types before running the code.
ggplot2::ggplot(data, aes(...)) - aes() Expanded reference ↗
- Map data variables to graphical features such as x, y or colour. Check argument names and data types before running the code.
ggplot2::aes(x=..., y=..., colour=...) - geom_histogram() Expanded reference ↗
- Draw bins showing a distribution of numeric values. Check argument names and data types before running the code.
ggplot2::geom_histogram(binwidth=...) - scale_x_continuous() Expanded reference ↗
- Control the continuous x-axis scale and tick marks. Check argument names and data types before running the code.
ggplot2::scale_x_continuous(breaks=...) - theme_classic() Expanded reference ↗
- Apply a simple plotting theme with minimal background decoration. Check argument names and data types before running the code.
ggplot2::theme_classic() - labs() Expanded reference ↗
- Set plot titles, axis labels and legend text. Check argument names and data types before running the code.
ggplot2::labs(x="...", y="...", title="...") - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
A histogram displays the frequency distribution of AQTotal. Binwidth=1 and boundary=-0.5 align bins to integer scores from 0 to 10.
A histogram shows frequency across score bins. AQ totals are integer-valued, so binwidth=1 with appropriate boundaries avoids splitting equal integer scores across arbitrary intervals. The bar heights describe the sample, not the general population.
Step-by-step classroom instructions
- Define a ggplot object for the AQ total-score distribution.
- Add a histogram layer with a bin width of one point.
- Display the completed AQ histogram.
Masterclass learning goals
Learning goal: Plot the integer-valued AQTotal distribution with bins of one.
Concept: Histograms for discrete integer-valued scores.
Original task checklist
Task instructions — what the student must do
- Define a ggplot object for the AQ total-score distribution.
- Add a histogram layer with a bin width of one point.
- Display the completed AQ histogram.
Instructor's teaching method and common pitfalls
Ask whether the distribution is symmetric, discrete and concentrated at low scores.
Common trap / interpretation warning
The familiar normal '68% within 1 SD' rule need not hold for a bounded discrete score.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
A histogram shows frequency across score bins. AQ totals are integer-valued, so binwidth=1 with appropriate boundaries avoids splitting equal integer scores across arbitrary intervals. The bar heights describe the sample, not the general population.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Define a ggplot object for the AQ total-score distribution.
# p_aq <- ggplot2::ggplot(
# Step 2. Add a histogram layer with a bin width of one point.
# ggplot2::geom_histogram(
# Step 3. Display the completed AQ histogram.
# print(p_aqInstructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Build a plot and specify how data map to visual variables.
p_aq <- ggplot2::ggplot(aq_scores,ggplot2::aes(x=AQTotal)) +
# NOTE: Add a visual layer; ggplot layers are combined with +.
ggplot2::geom_histogram(binwidth=1,boundary=-0.5,colour="white") +
# NOTE: Apply a plot theme; styling does not change source data.
ggplot2::scale_x_continuous(breaks=0:10) + ggplot2::theme_classic() +
# NOTE: Set interpretable axis labels and titles.
ggplot2::labs(x="AQ-10 score",y="Number of participants",title="AQ-10 score distribution")
# NOTE: Show the result in the Console (or display a ggplot object).
print(p_aq)Expected output, excerpts and validation checks
[Plot] Ten-point integer-scale histogram; x-axis 0–10, y-axis participant counts.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W3-E01 Additional: variance, SE, missingness
MOODLE SOURCE NOTE: ferdo Lab original extension. INDEPENDENT ADDITION (not an official Moodle task).
R functions and syntax reference · 6 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- var() Expanded reference ↗
- Calculate the sample variance. Variance has squared measurement units.
var(x) - sd() Expanded reference ↗
- Calculate the sample standard deviation. With the default sample definition, SD uses n−1 in the denominator.
sd(x) - sqrt() Expanded reference ↗
- Calculate the non-negative square root. Check argument names and data types before running the code.
sqrt(x) - nrow() Expanded reference ↗
- Count the number of rows in a table. Check argument names and data types before running the code.
nrow(data) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
Sample variance expresses squared dispersion (units of Score²); sample standard deviation retains score units. Standard error measures estimated uncertainty in the sample mean, not individual differences.
Variance is expressed in squared units; SD returns to the original score units. The standard error of a sample mean is approximately SD/sqrt(n) for independent identically distributed observations. SE quantifies precision of the estimated mean, not participant variability.
Step-by-step classroom instructions
- Compute the sample variance of the AQ total scores.
- Compute the standard error using SD divided by the square root of n.
- Print variance and standard error with meaningful labels.
Masterclass learning goals
Learning goal: Explain why SD measures spread while SE relates to the sample mean.
Concept: Variance, standard deviation, standard error and missingness.
Original task checklist
Task instructions — what the student must do
- Compute the sample variance of the AQ total scores.
- Compute the standard error using SD divided by the square root of n.
- Print variance and standard error with meaningful labels.
Instructor's teaching method and common pitfalls
Show SE = SD / sqrt(n) and discuss how doubling n affects SE.
Common trap / interpretation warning
Variance, SD and SE answer different questions. Do not substitute SE for SD on participant-level charts.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
Variance is expressed in squared units; SD returns to the original score units. The standard error of a sample mean is approximately SD/sqrt(n) for independent identically distributed observations. SE quantifies precision of the estimated mean, not participant variability.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Compute the sample variance of the AQ total scores.
# variance_aq <- var(
# Step 2. Compute the standard error using SD divided by the square root of n.
# se_aq <- sd(
# Step 3. Print variance and standard error with meaningful labels.
# print(c(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Compute sample variance (square of SD).
variance_aq <- var(aq_scores$AQTotal) # Sample variance (n-1 denominator).
# NOTE: Compute a sample standard deviation.
se_aq <- sd(aq_scores$AQTotal)/sqrt(nrow(aq_scores))
# NOTE: Show the result in the Console (or display a ggplot object).
print(c(sample_variance=variance_aq, standard_error=se_aq))Expected output, excerpts and validation checks
sample_variance standard_error
# Two positive numeric values; data-dependent.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
Visualisation with ggplot2
Original Teacher's Kit — Week 4: teaching notes, alternative demonstration and line-by-line R analysis
Data visualisation and graphical reasoning
Choose suitable plot types, label axes and describe distributions or associations without causal claims.
Expected output and interpretation
Twelve fictional ATSQ rows join with background by id. Group mean score: Coding=Yes 2.38, Coding=No ≈3.114. Histograms show one-variable distributions; scatterplots show associations; boxplots show medians/quartiles, not these group means.
Live demonstration
Ask 'Which question should this chart answer?' before plotting. Check the student knows a standard boxplot depicts the median and IQR.
R script: line-by-line explanation
The table shows executable lines from the openly published, original solution. Continuation lines of multi-line calls are explained separately.
| R code | What exactly happens? |
|---|---|
01atsq <- read.csv("data/atsq.csv") | Reads fictional score totals; this file alone lacks background covariates. |
02background <- read.csv("data/background.csv") | Reads age and Coding background variables from a separate CSV. |
03d <- merge(atsq,background,by="id") | An inner join by id retains only participants present in both files. |
04print(head(d)) | head(d) quickly inspects the first six joined records. |
05hist(d$atsqTotal,breaks=5,main="Synthetic ATSQ totals", | hist() shows a single numeric distribution; breaks=5 requests an approximate bin arrangement. |
06xlab="Illustrative score") | xlab names the axis; do not invent a unit when it is not established. |
07plot(d$age,d$atsqTotal,pch=19,xlab="Age",ylab="Synthetic ATSQ score") | plot(x,y) places two quantitative variables on axes; pch=19 draws solid dots. |
08boxplot(atsqTotal~Coding,data=d,xlab="Prior coding", | atsqTotal~Coding groups the score distribution by categorical Coding values. |
09ylab="Synthetic ATSQ score",main="Distribution by coding") | ylab and main supply the axis label and chart title. |
10print(aggregate(atsqTotal~Coding,d,mean)) | aggregate() reports group means; this does NOT mean the boxplot box represents a mean. |
11stopifnot(nrow(d)==12L,all(is.finite(d$atsqTotal))) | Checks 12 joined rows and that all scores are finite numeric values. |
12cat("W4 PASS: 12 synthetic matched records\n") | Prints a code-check message; it does not validate the plot interpretation. |
Likely misconception
A boxplot is not mean±SD. A scatterplot is not causal evidence; the invented ATSQ variable has no verified clinical scale interpretation.
Exit check
Why use a scatterplot for age versus score? What does a box represent? What is the n=12 limitation?
W4-M01 Histogram and binwidth
MOODLE SOURCE NOTE: wk4_practical_visualisation.r · Part 1 histogram. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 6 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- ggplot() Expanded reference ↗
- Start a layered grammar-of-graphics plot. Check argument names and data types before running the code.
ggplot2::ggplot(data, aes(...)) - aes() Expanded reference ↗
- Map data variables to graphical features such as x, y or colour. Check argument names and data types before running the code.
ggplot2::aes(x=..., y=..., colour=...) - geom_histogram() Expanded reference ↗
- Draw bins showing a distribution of numeric values. Check argument names and data types before running the code.
ggplot2::geom_histogram(binwidth=...) - labs() Expanded reference ↗
- Set plot titles, axis labels and legend text. Check argument names and data types before running the code.
ggplot2::labs(x="...", y="...", title="...") - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - + Expanded reference ↗
- Add a graphics layer; here + combines plot components, not numbers.
ggplot(...) + geom_histogram(...)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
Histogram binwidth controls aggregation granularity. A five-point bin gives a broad overview, whereas a one-point bin reveals local discreteness and noise.
Histograms reveal concentration, skewness and possible unusual values. Reducing binwidth creates more, narrower bins; it does not change the data. The horizontal scale and sample size should remain clear when comparing visual appearances.
Step-by-step classroom instructions
- Start a ggplot of the distribution of AHI scores.
- Add a histogram with a chosen bin width, then compare alternatives.
- Print the finished histogram.
Masterclass learning goals
Learning goal: Create an AHI histogram; compare bins 5 and 1.
Concept: Distribution plots and the consequences of bin-width choices.
Original task checklist
Task instructions — what the student must do
- Start a ggplot of the distribution of AHI scores.
- Add a histogram with a chosen bin width, then compare alternatives.
- Print the finished histogram.
Instructor's teaching method and common pitfalls
Compare both plots without changing the underlying data and ask which binning supports the research question.
Common trap / interpretation warning
Histogram appearance depends strongly on breaks; avoid claiming a shape is inherent to the raw data.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
Histograms reveal concentration, skewness and possible unusual values. Reducing binwidth creates more, narrower bins; it does not change the data. The horizontal scale and sample size should remain clear when comparing visual appearances.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Start a ggplot of the distribution of AHI scores.
# p_hist <- ggplot2::ggplot(
# Step 2. Add a histogram with a chosen bin width, then compare alternatives.
# ggplot2::geom_histogram(
# Step 3. Print the finished histogram.
# print(p_histInstructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Build a plot and specify how data map to visual variables.
p_hist <- ggplot2::ggplot(all_data,ggplot2::aes(x=ahiTotal)) +
# NOTE: Add a visual layer; ggplot layers are combined with +.
ggplot2::geom_histogram(binwidth=5,colour="white") +
# NOTE: Set interpretable axis labels and titles.
ggplot2::labs(x="AHI total",y="Count",title="AHI distribution")
# NOTE: Show the result in the Console (or display a ggplot object).
print(p_hist)
# NOTE: Show the result in the Console (or display a ggplot object).
print(ggplot2::ggplot(all_data,ggplot2::aes(x=ahiTotal)) +
# NOTE: Add a visual layer; ggplot layers are combined with +.
ggplot2::geom_histogram(binwidth=1,colour="white") +
# NOTE: Set interpretable axis labels and titles.
ggplot2::labs(x="AHI total",y="Count",title="AHI distribution: binwidth 1"))Expected output, excerpts and validation checks
[Plot 1] AHI histogram with binwidth 5.
[Plot 2] The same distribution with binwidth 1.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W4-M02 Scatterplot and sex legend
MOODLE SOURCE NOTE: wk4_practical_visualisation.r · Part 1 scatterplot. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 8 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- mutate() Expanded reference ↗
- Create or alter one or more columns. Check argument names and data types before running the code.
dplyr::mutate(data, new=x+y) - factor() Expanded reference ↗
- Represent categorical values with ordered levels and labels. Incorrect levels or labels can reverse category meanings.
factor(x, levels=..., labels=...) - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - ggplot() Expanded reference ↗
- Start a layered grammar-of-graphics plot. Check argument names and data types before running the code.
ggplot2::ggplot(data, aes(...)) - aes() Expanded reference ↗
- Map data variables to graphical features such as x, y or colour. Check argument names and data types before running the code.
ggplot2::aes(x=..., y=..., colour=...) - geom_point() Expanded reference ↗
- Plot individual observations as points. Check argument names and data types before running the code.
ggplot2::geom_point() - labs() Expanded reference ↗
- Set plot titles, axis labels and legend text. Check argument names and data types before running the code.
ggplot2::labs(x="...", y="...", title="...") - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
A scatterplot maps each record to (AHI, CES-D). Mapping colour to sex_label adds a legend and groups without changing the underlying x/y coordinates.
A scatterplot shows paired observations for two numeric variables. Mapping colour inside aes() creates groups and a legend; setting colour outside aes() gives all points one colour. Correlation visible in a plot does not establish cause and effect. Verify categorical codebook labels.
Step-by-step classroom instructions
- Create meaningful factor labels for the sex variable using the codebook.
- Start a scatterplot of AHI against CES-D, coloured by the sex labels.
Masterclass learning goals
Learning goal: Show AHI–CES-D association, then colour points by sex.
Concept: Scatterplots, two numeric variables and categorical colour legends.
Original task checklist
Task instructions — what the student must do
- Create meaningful factor labels for the sex variable using the codebook.
- Start a scatterplot of AHI against CES-D, coloured by the sex labels.
Instructor's teaching method and common pitfalls
Discuss overplotting, transparency alpha and the fact that association does not establish causation.
Common trap / interpretation warning
Repeated observations for the same person can make apparent independence misleading.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
A scatterplot shows paired observations for two numeric variables. Mapping colour inside aes() creates groups and a legend; setting colour outside aes() gives all points one colour. Correlation visible in a plot does not establish cause and effect. Verify categorical codebook labels.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Create meaningful factor labels for the sex variable using the codebook.
# all_data <- dplyr::mutate(
# Step 2. Start a scatterplot of AHI against CES-D, coloured by the sex labels.
# p_scatter <- ggplot2::ggplot(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Create or recode columns while retaining row-level observations.
all_data <- dplyr::mutate(all_data,
# NOTE: Map numeric category codes to readable factor levels.
sex_label=factor(sex,levels=c(1,2),labels=c("Female","Male")))
# NOTE: Build a plot and specify how data map to visual variables.
p_scatter <- ggplot2::ggplot(all_data,
# NOTE: Apply the ggplot operation to the current visualisation.
ggplot2::aes(x=ahiTotal,y=cesdTotal,colour=sex_label)) +
# NOTE: Add a visual layer; ggplot layers are combined with +.
ggplot2::geom_point(alpha=0.48) +
# NOTE: Set interpretable axis labels and titles.
ggplot2::labs(x="AHI total",y="CES-D total",colour="Sex")
# NOTE: Show the result in the Console (or display a ggplot object).
print(p_scatter)Expected output, excerpts and validation checks
[Plot] AHI on x-axis; CES-D on y-axis; coloured points and a Female/Male legend.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W4-M03 Boxplot, violin, and raw points
MOODLE SOURCE NOTE: wk4_practical_visualisation.r · Part 1 box/violin. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 8 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- ggplot() Expanded reference ↗
- Start a layered grammar-of-graphics plot. Check argument names and data types before running the code.
ggplot2::ggplot(data, aes(...)) - aes() Expanded reference ↗
- Map data variables to graphical features such as x, y or colour. Check argument names and data types before running the code.
ggplot2::aes(x=..., y=..., colour=...) - factor() Expanded reference ↗
- Represent categorical values with ordered levels and labels. Incorrect levels or labels can reverse category meanings.
factor(x, levels=..., labels=...) - geom_boxplot() Expanded reference ↗
- Draw median, quartile and whisker summaries. The box is not a mean ± SD interval.
ggplot2::geom_boxplot() - labs() Expanded reference ↗
- Set plot titles, axis labels and legend text. Check argument names and data types before running the code.
ggplot2::labs(x="...", y="...", title="...") - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - geom_violin() Expanded reference ↗
- Draw smoothed density shapes by group. Check argument names and data types before running the code.
ggplot2::geom_violin() - geom_jitter() Expanded reference ↗
- Add small position offsets to reveal overlapping points. Check argument names and data types before running the code.
ggplot2::geom_jitter(width=...)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
A boxplot summarises median, quartiles and whiskers; a violin plot displays a smoothed distribution density. Jittered points preserve visibility of individual observations.
A standard boxplot displays the median and quartiles, with whiskers following a rule such as 1.5 times the IQR. It is not a mean ± SD plot. A violin plot displays a smoothed density estimate, whose shape depends on smoothing and sample size; raw points can help.
Step-by-step classroom instructions
- Create a ggplot object that compares the outcome across groups.
- Add a boxplot layer to display medians and quartiles.
- Create a separate violin plot to show the shape of group distributions.
Masterclass learning goals
Learning goal: Recreate boxplot and add violin overlay; describe what each reveals.
Concept: Boxplots, violin plots, medians and interquartile ranges.
Original task checklist
Task instructions — what the student must do
- Create a ggplot object that compares the outcome across groups.
- Add a boxplot layer to display medians and quartiles.
- Create a separate violin plot to show the shape of group distributions.
Instructor's teaching method and common pitfalls
Compare whether both plot types tell a consistent story about occasion-level variation.
Common trap / interpretation warning
A standard boxplot does not show mean ± SD; and a violin density may exaggerate thin groups.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
A standard boxplot displays the median and quartiles, with whiskers following a rule such as 1.5 times the IQR. It is not a mean ± SD plot. A violin plot displays a smoothed density estimate, whose shape depends on smoothing and sample size; raw points can help.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Create a ggplot object that compares the outcome across groups.
# p_box <- ggplot2::ggplot(
# Step 2. Add a boxplot layer to display medians and quartiles.
# ggplot2::geom_boxplot(
# Step 3. Create a separate violin plot to show the shape of group distributions.
# p_violin <- ggplot2::ggplot(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Map numeric category codes to readable factor levels.
p_box <- ggplot2::ggplot(all_data,ggplot2::aes(x=factor(occasion),y=ahiTotal)) +
# NOTE: Add a visual layer; ggplot layers are combined with +.
ggplot2::geom_boxplot(fill="#7cccd2",outlier.alpha=.4) +
# NOTE: Set interpretable axis labels and titles.
ggplot2::labs(x="Occasion code",y="AHI total")
# NOTE: Show the result in the Console (or display a ggplot object).
print(p_box)
# NOTE: Map numeric category codes to readable factor levels.
p_violin <- ggplot2::ggplot(all_data,ggplot2::aes(x=factor(occasion),y=ahiTotal)) +
# NOTE: Add a visual layer; ggplot layers are combined with +.
ggplot2::geom_violin(fill="#c3aaf5",alpha=.55) +
# NOTE: Add a visual layer; ggplot layers are combined with +.
ggplot2::geom_boxplot(width=.13,outlier.shape=NA) +
# NOTE: Add a visual layer; ggplot layers are combined with +.
ggplot2::geom_jitter(width=.1,alpha=.15,size=.45)
# NOTE: Show the result in the Console (or display a ggplot object).
print(p_violin)Expected output, excerpts and validation checks
[Plot 1] AHI boxplot by occasion.
[Plot 2] Violin + narrow boxplot + jittered individual points.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W4-M04 Mean bar plot, grouped by intervention
MOODLE SOURCE NOTE: wk4_practical_visualisation.r · Part 1 bar plot. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 11 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- mutate() Expanded reference ↗
- Create or alter one or more columns. Check argument names and data types before running the code.
dplyr::mutate(data, new=x+y) - factor() Expanded reference ↗
- Represent categorical values with ordered levels and labels. Incorrect levels or labels can reverse category meanings.
factor(x, levels=..., labels=...) - group_by() Expanded reference ↗
- Set the grouping keys used by later operations. Remember to inspect or remove grouping after grouped summaries.
dplyr::group_by(data, group) - summarise() Expanded reference ↗
- Produce summary statistics for the whole table or each group. Check argument names and data types before running the code.
dplyr::summarise(data, metric=mean(x)) - mean() Expanded reference ↗
- Calculate an arithmetic average. Use na.rm=TRUE to omit missing values explicitly.
mean(x, na.rm=FALSE) - ggplot() Expanded reference ↗
- Start a layered grammar-of-graphics plot. Check argument names and data types before running the code.
ggplot2::ggplot(data, aes(...)) - aes() Expanded reference ↗
- Map data variables to graphical features such as x, y or colour. Check argument names and data types before running the code.
ggplot2::aes(x=..., y=..., colour=...) - geom_col() Expanded reference ↗
- Draw bars using already-calculated y values. Check argument names and data types before running the code.
ggplot2::geom_col() - n() Expanded reference ↗
- Return the number of rows in the active dplyr group. Check argument names and data types before running the code.
dplyr::n() - sd() Expanded reference ↗
- Calculate the sample standard deviation. With the default sample definition, SD uses n−1 in the denominator.
sd(x) - |> Expanded reference ↗
- Pass a data frame through consecutive transformations.
data |> group_by(...)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
The summary table calculates means before plotting. geom_col() treats its y value as a precomputed height, unlike geom_bar() which counts observations by default.
If means have already been calculated in a summary table, geom_col() displays those values as bar heights. geom_bar() instead counts rows by default. Grouping by intervention provides distinct means but does not prove any intervention caused a difference.
Step-by-step classroom instructions
- Create readable labels for the intervention groups.
- Start a pipeline from the full data to calculate group means.
- Group the data by intervention before calculating each mean.
- Start a bar chart of the precomputed group means.
Masterclass learning goals
Learning goal: Compute means, then plot overall and grouped means.
Concept: Group means and bar plots of precomputed summaries.
Original task checklist
Task instructions — what the student must do
- Create readable labels for the intervention groups.
- Start a pipeline from the full data to calculate group means.
- Group the data by intervention before calculating each mean.
- Start a bar chart of the precomputed group means.
Instructor's teaching method and common pitfalls
Explain why the 'dodge' position separates intervention groups within an occasion.
Common trap / interpretation warning
Compare denominators n by group, and do not mistake a descriptive bar difference for a tested effect.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
If means have already been calculated in a summary table, geom_col() displays those values as bar heights. geom_bar() instead counts rows by default. Grouping by intervention provides distinct means but does not prove any intervention caused a difference.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Create readable labels for the intervention groups.
# intervention_labels <- c(
# Step 2. Start a pipeline from the full data to calculate group means.
# means_groups <- all_data |>
# Step 3. Group the data by intervention before calculating each mean.
# dplyr::group_by(
# Step 4. Start a bar chart of the precomputed group means.
# p_bar <- ggplot2::ggplot(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Create human-readable labels for coded intervention groups.
intervention_labels <- c("Signature strengths","Three good things",
# NOTE: Continue this R expression with its arguments, values or formatting.
"Gratitude visit","Early memories (control)")
# NOTE: Create or recode columns while retaining row-level observations.
all_data <- dplyr::mutate(all_data, intervention_label=factor(intervention,
# NOTE: Continue this R expression with its arguments, values or formatting.
levels=1:4,labels=intervention_labels))
# NOTE: Assign the computed result to a named R object.
means_occasion <- all_data |>
# NOTE: Define the groups to be summarised independently.
dplyr::group_by(occasion) |>
# NOTE: Reduce each group to its aggregate statistics.
dplyr::summarise(mean_ahi=mean(ahiTotal),.groups="drop")
# NOTE: Show the result in the Console (or display a ggplot object).
print(ggplot2::ggplot(means_occasion,ggplot2::aes(x=factor(occasion),y=mean_ahi))+
# NOTE: Add a visual layer; ggplot layers are combined with +.
ggplot2::geom_col(fill="#9fd8c2"))
# NOTE: Assign the computed result to a named R object.
means_groups <- all_data |>
# NOTE: Define the groups to be summarised independently.
dplyr::group_by(occasion,intervention_label) |>
# NOTE: Reduce each group to its aggregate statistics.
dplyr::summarise(n=dplyr::n(),mean_ahi=mean(ahiTotal),sd_ahi=sd(ahiTotal),
# NOTE: Specify how groups, missing values or join keys are handled.
.groups="drop")
# NOTE: Show the result in the Console (or display a ggplot object).
print(ggplot2::ggplot(means_groups,ggplot2::aes(x=factor(occasion),y=mean_ahi,
# NOTE: Add a visual layer; ggplot layers are combined with +.
fill=intervention_label)) + ggplot2::geom_col(position="dodge"))Expected output, excerpts and validation checks
[Plot 1] One mean-AHI bar per occasion.
[Plot 2] Side-by-side intervention mean bars per occasion.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W4-M05 Line plot and SD error bars
MOODLE SOURCE NOTE: wk4_practical_visualisation.r · Part 1 line + ylim + SD. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 9 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- ggplot() Expanded reference ↗
- Start a layered grammar-of-graphics plot. Check argument names and data types before running the code.
ggplot2::ggplot(data, aes(...)) - aes() Expanded reference ↗
- Map data variables to graphical features such as x, y or colour. Check argument names and data types before running the code.
ggplot2::aes(x=..., y=..., colour=...) - geom_line() Expanded reference ↗
- Connect points in x-axis order within groups. Check argument names and data types before running the code.
ggplot2::geom_line() - geom_point() Expanded reference ↗
- Plot individual observations as points. Check argument names and data types before running the code.
ggplot2::geom_point() - geom_errorbar() Expanded reference ↗
- Draw uncertainty or variability intervals between ymin and ymax. Label whether intervals are SD, SE or confidence intervals.
ggplot2::geom_errorbar(aes(ymin=..., ymax=...)) - coord_cartesian() Expanded reference ↗
- Zoom a plot to a selected viewing range without discarding data. Check argument names and data types before running the code.
ggplot2::coord_cartesian(ylim=c(lo, hi)) - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - labs() Expanded reference ↗
- Set plot titles, axis labels and legend text. Check argument names and data types before running the code.
ggplot2::labs(x="...", y="...", title="...") - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
A group is tracked through time using colour and group aesthetics. The vertical bars run from mean − SD to mean + SD; they describe dispersion, not a 95% confidence interval.
A line plot connecting occasion-level means visualises a sequence of group summaries. These are not necessarily trajectories of the same individual. Error bars labelled ±1 SD describe within-group variability and are not the same as standard errors or 95% confidence intervals.
Step-by-step classroom instructions
- Start a plot of group mean scores across measurement occasions.
- Add a line layer connecting the occasion means.
- Add error bars for plus/minus one standard deviation, not a confidence interval.
Masterclass learning goals
Learning goal: Create line plot with 24–120 display range and ±1 SD bars.
Concept: Time-series group summaries and standard-deviation error bars.
Original task checklist
Task instructions — what the student must do
- Start a plot of group mean scores across measurement occasions.
- Add a line layer connecting the occasion means.
- Add error bars for plus/minus one standard deviation, not a confidence interval.
Instructor's teaching method and common pitfalls
Read two occasion points on a line and compare the within-group direction of change.
Common trap / interpretation warning
coord_cartesian() zooms without filtering original data; SD bars must not be called confidence intervals.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
A line plot connecting occasion-level means visualises a sequence of group summaries. These are not necessarily trajectories of the same individual. Error bars labelled ±1 SD describe within-group variability and are not the same as standard errors or 95% confidence intervals.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Start a plot of group mean scores across measurement occasions.
# p_line <- ggplot2::ggplot(
# Step 2. Add a line layer connecting the occasion means.
# ggplot2::geom_line(
# Step 3. Add error bars for plus/minus one standard deviation, not a confidence interval.
# ggplot2::geom_errorbar(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Build a plot and specify how data map to visual variables.
p_line <- ggplot2::ggplot(means_groups,
# NOTE: Apply the ggplot operation to the current visualisation.
ggplot2::aes(x=occasion,y=mean_ahi,colour=intervention_label,group=intervention_label)) +
# NOTE: Add a visual layer; ggplot layers are combined with +.
ggplot2::geom_line() + ggplot2::geom_point() +
# NOTE: Add a visual layer; ggplot layers are combined with +.
ggplot2::geom_errorbar(ggplot2::aes(ymin=mean_ahi-sd_ahi,ymax=mean_ahi+sd_ahi),
# NOTE: Specify how groups, missing values or join keys are handled.
width=.13,na.rm=TRUE) + ggplot2::coord_cartesian(ylim=c(24,120)) +
# NOTE: Set interpretable axis labels and titles.
ggplot2::labs(x="Measurement occasion (0=pre, 1=post)",y="Mean AHI ± 1 SD")
# NOTE: Show the result in the Console (or display a ggplot object).
print(p_line)Expected output, excerpts and validation checks
[Plot] Intervention mean-AHI trajectories across occasions with vertical ±1 SD error bars.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W4-M06 Themes, labels, facets and point style
MOODLE SOURCE NOTE: wk4_practical_visualisation.r · Part 2 themes / labels / facet / size-shape-colour. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).
R functions and syntax reference · 8 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - theme_classic() Expanded reference ↗
- Apply a simple plotting theme with minimal background decoration. Check argument names and data types before running the code.
ggplot2::theme_classic() - labs() Expanded reference ↗
- Set plot titles, axis labels and legend text. Check argument names and data types before running the code.
ggplot2::labs(x="...", y="...", title="...") - theme_bw() Expanded reference ↗
- Apply a black-and-white plotting theme. Check argument names and data types before running the code.
ggplot2::theme_bw() - facet_wrap() Expanded reference ↗
- Split a plot into small panels by one or more grouping variables. Check argument names and data types before running the code.
ggplot2::facet_wrap(~ group) - ggplot() Expanded reference ↗
- Start a layered grammar-of-graphics plot. Check argument names and data types before running the code.
ggplot2::ggplot(data, aes(...)) - aes() Expanded reference ↗
- Map data variables to graphical features such as x, y or colour. Check argument names and data types before running the code.
ggplot2::aes(x=..., y=..., colour=...) - geom_point() Expanded reference ↗
- Plot individual observations as points. Check argument names and data types before running the code.
ggplot2::geom_point()
Concepts, learning goals and student instructions
What this teaches — concept breakdown
Themes affect styling, titles communicate meaning and facet_wrap() creates panels by category. Geometric point aesthetics such as shape and alpha change appearance, not the observations.
ggplot objects combine datasets, aesthetic mappings, geometric layers, scales and themes. A theme changes presentation rather than numerical values; facet_wrap splits one plot into group panels. Always label axes, units and the meaning of visual encodings.
Step-by-step classroom instructions
- Print the existing scatterplot using a classic ggplot theme.
- Print a faceted version of the scatterplot, separated by the sex labels.
Masterclass learning goals
Learning goal: Compare themes, add titles, facet by sex, style points.
Concept: ggplot2 layers, themes, faceting and graphical annotations.
Original task checklist
Task instructions — what the student must do
- Print the existing scatterplot using a classic ggplot theme.
- Print a faceted version of the scatterplot, separated by the sex labels.
Instructor's teaching method and common pitfalls
Ask which version best reveals subgroup patterns and whether the colours should also encode a variable.
Common trap / interpretation warning
Visual style is not evidence of a statistical effect; transparency influences visibility.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
ggplot objects combine datasets, aesthetic mappings, geometric layers, scales and themes. A theme changes presentation rather than numerical values; facet_wrap splits one plot into group panels. Always label axes, units and the meaning of visual encodings.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Print the existing scatterplot using a classic ggplot theme.
# print(p_scatter + ggplot2::theme_classic(
# Step 2. Print a faceted version of the scatterplot, separated by the sex labels.
# print(p_scatter + ggplot2::facet_wrap(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Show the result in the Console (or display a ggplot object).
print(p_scatter + ggplot2::theme_classic() +
# NOTE: Set interpretable axis labels and titles.
ggplot2::labs(title="Happiness and depressive symptoms"))
# NOTE: Show the result in the Console (or display a ggplot object).
print(p_scatter + ggplot2::theme_bw() + ggplot2::facet_wrap(~sex_label))
# NOTE: Show the result in the Console (or display a ggplot object).
print(ggplot2::ggplot(all_data,ggplot2::aes(x=ahiTotal,y=cesdTotal)) +
# NOTE: Add a visual layer; ggplot layers are combined with +.
ggplot2::geom_point(colour="purple",size=2,shape=17,alpha=.3) +
# NOTE: Set interpretable axis labels and titles.
ggplot2::labs(title="Styled scatterplot",x="AHI",y="CES-D"))Expected output, excerpts and validation checks
[Plot 1] Classic scatter with title.
[Plot 2] Black-and-white faceted scatter by sex.
[Plot 3] Purple triangle scatter.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W4-E01 Additional: correlation and ATSQ context
MOODLE SOURCE NOTE: ferdo Lab original extension; ATSQ file is separate from original W4 plot tasks. INDEPENDENT ADDITION (not an official Moodle task).
R functions and syntax reference · 6 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- cor() Expanded reference ↗
- Calculate a correlation coefficient, Pearson by default. Correlation does not establish causation.
cor(x, y, use="complete.obs") - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - read.csv() Expanded reference ↗
- Read a comma-separated file into a data frame. Check argument names and data types before running the code.
read.csv("data/file.csv", stringsAsFactors=FALSE) - inner_join() Expanded reference ↗
- Keep and combine rows whose keys match in both tables. Check join keys, missing matches and possible duplicate-key expansion.
dplyr::inner_join(x, y, by="id") - nrow() Expanded reference ↗
- Count the number of rows in a table. Check argument names and data types before running the code.
nrow(data)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
cor() gives a descriptive linear association coefficient for AHI and CES-D using complete cases. The second join illustrates linking two other tables by participant id.
The Pearson correlation coefficient describes the direction and strength of a linear association, typically between -1 and 1. It does not identify a causal mechanism. ATSQ is a separate scale whose substantive meaning has not been verified in these teaching materials.
Step-by-step classroom instructions
- Calculate the correlation between AHI and CES-D with missing-data handling.
- Import the separately supplied ATSQ scores as a data frame.
- Join ATSQ scores to participant information by participant ID.
Masterclass learning goals
Learning goal: Distinguish graphical association from causal effect; inspect separate ATSQ join.
Concept: Correlation is association, not causation; use caution with ATSQ.
Original task checklist
Task instructions — what the student must do
- Calculate the correlation between AHI and CES-D with missing-data handling.
- Import the separately supplied ATSQ scores as a data frame.
- Join ATSQ scores to participant information by participant ID.
Instructor's teaching method and common pitfalls
Contrast a correlation within repeated measurements with independent participant-level correlations.
Common trap / interpretation warning
Correlation does not prove causality; missing pairs and repeated observations require care.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
The Pearson correlation coefficient describes the direction and strength of a linear association, typically between -1 and 1. It does not identify a causal mechanism. ATSQ is a separate scale whose substantive meaning has not been verified in these teaching materials.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Calculate the correlation between AHI and CES-D with missing-data handling.
# cor_ahi_cesd <- cor(
# Step 2. Import the separately supplied ATSQ scores as a data frame.
# atsq <- read.csv(
# Step 3. Join ATSQ scores to participant information by participant ID.
# atsq_merged <- dplyr::inner_join(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Compute the Pearson linear correlation coefficient.
cor_ahi_cesd <- cor(all_data$ahiTotal,all_data$cesdTotal,use="complete.obs")
# NOTE: Show the result in the Console (or display a ggplot object).
print(c(correlation=cor_ahi_cesd))
# NOTE: Read an input CSV into a data frame; check the working directory.
atsq <- read.csv("data/atsq_scores.csv",stringsAsFactors=FALSE)
# NOTE: Read an input CSV into a data frame; check the working directory.
p_background <- read.csv("data/p_info.csv",stringsAsFactors=FALSE)
# NOTE: Join matching records using the specified key columns.
atsq_joint <- dplyr::inner_join(atsq,p_background,by="id")
# NOTE: Show the result in the Console (or display a ggplot object).
print(c(atsq_rows=nrow(atsq),background_rows=nrow(p_background),joined=nrow(atsq_joint)))Expected output, excerpts and validation checks
correlation
# One coefficient in [-1,1].
atsq_rows background_rows joined
# Three data-dependent row counts.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
Sampling and bootstrap simulations
Original Teacher's Kit — Week 5: teaching notes, alternative demonstration and line-by-line R analysis
Sampling, SD, SE and simulation — provisional
Distinguish individual spread (SD) from sampling variability of the mean (SE) and implement a reproducible resampling simulation.
Expected output and interpretation
For 12 invented response times, the mean is 606.75 ms, sample SD ≈10.332 ms and SE ≈2.983 ms. Resample sizes 4 and 10 can be compared; seeded simulation values are reproducible in the same R environment.
Live demonstration
Ask which measure reflects differences among people versus uncertainty of a mean. Plot side by side and compare variability as resample size increases.
R script: line-by-line explanation
The table shows executable lines from the openly published, original solution. Continuation lines of multi-line calls are explained separately.
| R code | What exactly happens? |
|---|---|
01rt_ms <- c(620,610,590,605,615,600,625,595,608,612,598,603) | c() creates a vector of 12 fabricated response times in milliseconds. |
02n <- length(rt_ms) | length() returns the number of observations: n=12. |
03mean_rt <- mean(rt_ms) | mean() computes mean response time: 606.75 ms. |
04sd_rt <- sd(rt_ms) | sd() calculates sample standard deviation using n−1: approximately 10.332 ms. |
05se_rt <- sd_rt / sqrt(n) | sd/sqrt(n) estimates the standard error of the mean under independent, identically distributed sampling: about 2.983 ms. |
06print(c(n=n, mean_ms=mean_rt, sd_ms=sd_rt, se_ms=se_rt)) | c() creates a named summary vector; print() displays it. |
07stopifnot(n==12L, is.finite(se_rt), se_rt>0) | stopifnot() asserts n=12 and that SE is finite and positive. |
08set.seed(46) | set.seed(46) makes the pseudo-random simulation reproducible. |
09means_n4 <- replicate(1000, mean(sample(rt_ms, 4, replace=TRUE))) | replicate(1000,...) samples four values with replacement and stores the mean 1,000 times. |
10means_n10 <- replicate(1000, mean(sample(rt_ms, 10, replace=TRUE))) | Repeats sampling with replacement using size 10; mean estimates tend to vary less. |
11par(mfrow=c(1,2)) | par(mfrow=c(1,2)) arranges plots in one row and two columns. |
12hist(means_n4, main="Resample size = 4", xlab="Mean RT (ms)") | Plots resampled means at n=4, NOT a histogram of individual reaction times. |
13hist(means_n10, main="Resample size = 10", xlab="Mean RT (ms)") | Plots simulated sample means at n=10; the x-axis remains in milliseconds. |
14par(mfrow=c(1,1)) | par(mfrow=c(1,1)) restores a single-plot layout. |
15print(c(sd_n4=sd(means_n4),sd_n10=sd(means_n10))) | Compares simulation-based spread of sample means at n=4 versus n=10. |
16means_n12 <- replicate(1000, mean(sample(rt_ms, n, replace=TRUE))) | Generates 1,000 size-12 bootstrap sample means to match the original sample size. |
17print(quantile(means_n12,c(.025,.975))) | quantile(...,.025,.975) gives a percentile interval from size-12 bootstrap means; its validity depends on sampling assumptions. |
18stopifnot(length(means_n4)==1000L, all(is.finite(means_n12))) | Checks that simulation vectors have the expected length and finite values. |
19cat("WEEK 5 WORKED EXAMPLE PASS\n") | cat() prints a test banner, not a statistical finding. |
Likely misconception
set.seed() guarantees reproducibility, not representativeness. Resample means at n=10 do not form a standard bootstrap percentile CI for the observed n=12 mean. Thus we separately resample n=12; even that cannot validate population inference from a fabricated sample.
Exit check
What units do SD and SE use? What does replace=TRUE do? Why cannot bootstrapping rescue a nonrepresentative sample?
W5-E01 Sampling distributions and descriptive variation
MOODLE SOURCE NOTE: Independent ferdo Lab provisional lesson; no verified Moodle Week 5 file. INDEPENDENT ADDITION (not an official Moodle task).
R functions and syntax reference · 6 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - length() Expanded reference ↗
- Return the number of elements in a vector. Check argument names and data types before running the code.
length(x) - mean() Expanded reference ↗
- Calculate an arithmetic average. Use na.rm=TRUE to omit missing values explicitly.
mean(x, na.rm=FALSE) - sd() Expanded reference ↗
- Calculate the sample standard deviation. With the default sample definition, SD uses n−1 in the denominator.
sd(x) - sqrt() Expanded reference ↗
- Calculate the non-negative square root. Check argument names and data types before running the code.
sqrt(x) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
The mean gives the centre of a numerical sample; SD estimates trial-to-trial dispersion; SE estimates the precision of the sample mean under independence.
SD measures the spread of observations; the standard error (SE) estimates uncertainty in the mean. Under standard independent-sampling assumptions SE≈SD/sqrt(n); as n increases, the SE of a mean tends to decrease. This does not resolve sampling bias.
Step-by-step classroom instructions
- Create a short fictional sample of reaction times in milliseconds.
- Calculate how many reaction times are in the sample.
- Calculate the sample mean reaction time.
Masterclass learning goals
Learning goal: Compare SD of observed times and standard error of their mean.
Concept: Sampling, sample variability, SD and SE of the sample mean.
Original task checklist
Task instructions — what the student must do
- Create a short fictional sample of reaction times in milliseconds.
- Calculate how many reaction times are in the sample.
- Calculate the sample mean reaction time.
Instructor's teaching method and common pitfalls
Have learners predict that SE is smaller than SD when n > 1.
Common trap / interpretation warning
Fictional trial values illustrate estimation only, not generalisable experimental results.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
SD measures the spread of observations; the standard error (SE) estimates uncertainty in the mean. Under standard independent-sampling assumptions SE≈SD/sqrt(n); as n increases, the SE of a mean tends to decrease. This does not resolve sampling bias.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Create a short fictional sample of reaction times in milliseconds.
# rt_demo <- c(
# Step 2. Calculate how many reaction times are in the sample.
# rt_n <- length(
# Step 3. Calculate the sample mean reaction time.
# rt_mean <- mean(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Define an illustrative vector of fictional reaction times.
rt_demo <- c(620,610,590,605,615,600,625,595,608,612,598,603)
# NOTE: Assign the computed result to a named R object.
rt_n <- length(rt_demo)
# NOTE: Compute an arithmetic mean of the selected numbers.
rt_mean <- mean(rt_demo)
# NOTE: Compute a sample standard deviation.
rt_sd <- sd(rt_demo)
# NOTE: Assign the computed result to a named R object.
rt_se <- rt_sd / sqrt(rt_n)
# NOTE: Show the result in the Console (or display a ggplot object).
print(c(n=rt_n,mean_ms=rt_mean,sd_ms=rt_sd,se_ms=rt_se))Expected output, excerpts and validation checks
n = 12
mean_ms = 606.75
sd_ms ≈ 10.3320
se_ms ≈ 2.9826Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W5-E02 Resampling and bootstrap percentile interval
MOODLE SOURCE NOTE: Independent ferdo Lab provisional lesson; no verified Moodle Week 5 file. INDEPENDENT ADDITION (not an official Moodle task).
R functions and syntax reference · 9 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- set.seed() Expanded reference ↗
- Fix the pseudorandom generator state for reproducible output. Check argument names and data types before running the code.
set.seed(46) - replicate() Expanded reference ↗
- Evaluate an expression repeatedly and collect the results. Check argument names and data types before running the code.
replicate(B, expression) - mean() Expanded reference ↗
- Calculate an arithmetic average. Use na.rm=TRUE to omit missing values explicitly.
mean(x, na.rm=FALSE) - sample() Expanded reference ↗
- Draw elements with or without replacement. Bootstrap sampling usually uses replace=TRUE and the observed sample size.
sample(x, size, replace=TRUE) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - sd() Expanded reference ↗
- Calculate the sample standard deviation. With the default sample definition, SD uses n−1 in the denominator.
sd(x) - quantile() Expanded reference ↗
- Calculate the requested percentiles of a vector. A percentile interval is only as credible as its resampling assumptions.
quantile(x, probs=c(.025,.975)) - replace=TRUE Expanded reference ↗
- Allow an observed data point to appear more than once in a resample.
sample(x, n, replace=TRUE)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
Bootstrap sampling with replacement builds a distribution of resampled means. Larger resample sizes usually produce narrower distributions; percentile intervals use quantiles of resampled statistics.
Bootstrap resampling draws observations with replacement from the observed sample. Sampling n=4 versus n=10 illustrates different variability of resampled means, whereas a bootstrap percentile interval for the observed n=12 mean should resample n=12. Set the seed for reproducibility.
Step-by-step classroom instructions
- Set the random seed so the resampling results can be reproduced.
- Simulate 1,000 resampled means using a sample size of four.
- Simulate 1,000 resampled means using a sample size of ten.
- Simulate a bootstrap distribution using the observed sample size.
Masterclass learning goals
Learning goal: Observe spread of mean for resampling n=4 vs n=10; use n=12 for the bootstrap CI.
Concept: Resampling distributions, reproducibility and percentile bootstrap intervals.
Original task checklist
Task instructions — what the student must do
- Set the random seed so the resampling results can be reproduced.
- Simulate 1,000 resampled means using a sample size of four.
- Simulate 1,000 resampled means using a sample size of ten.
- Simulate a bootstrap distribution using the observed sample size.
Instructor's teaching method and common pitfalls
Identify the fixed seed, the number of replicates and why replace=TRUE matters.
Common trap / interpretation warning
The seed makes R reproducible, but no numeric bootstrap result is claimed without executing the R source.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
Bootstrap resampling draws observations with replacement from the observed sample. Sampling n=4 versus n=10 illustrates different variability of resampled means, whereas a bootstrap percentile interval for the observed n=12 mean should resample n=12. Set the seed for reproducibility.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Set the random seed so the resampling results can be reproduced.
# set.seed(
# Step 2. Simulate 1,000 resampled means using a sample size of four.
# means_n4 <- replicate(
# Step 3. Simulate 1,000 resampled means using a sample size of ten.
# means_n10 <- replicate(
# Step 4. Simulate a bootstrap distribution using the observed sample size.
# bootstrap_means <- replicate(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Fix the R pseudorandom sequence for reproducible simulation.
set.seed(46) # Fix pseudo-random seed for reproducibility.
# NOTE: Compute an arithmetic mean of the selected numbers.
means_n4 <- replicate(1000,mean(sample(rt_demo,4,replace=TRUE)))
# NOTE: Compute an arithmetic mean of the selected numbers.
means_n10 <- replicate(1000,mean(sample(rt_demo,10,replace=TRUE)))
# NOTE: Show the result in the Console (or display a ggplot object).
print(c(sd_n4=sd(means_n4),sd_n10=sd(means_n10)))
# NOTE: Compute an arithmetic mean of the selected numbers.
bootstrap_means <- replicate(1000,mean(sample(rt_demo,rt_n,replace=TRUE)))
# NOTE: Extract specified percentile values from the resampling distribution.
bootstrap_ci <- quantile(bootstrap_means,c(.025,.975))
# NOTE: Show the result in the Console (or display a ggplot object).
print(bootstrap_ci)Expected output, excerpts and validation checks
sd_n4 sd_n10
# Two simulation SDs (typically sd_n10 < sd_n4).
2.5% 97.5%
# Two bootstrap percentile endpoints; exact values require running R.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W5-E03 Visualising the resampling distributions
MOODLE SOURCE NOTE: Independent ferdo Lab provisional lesson. INDEPENDENT ADDITION (not an official Moodle task).
R functions and syntax reference · 3 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- par() Expanded reference ↗
- Set graphical parameters such as the plot-panel layout. Check argument names and data types before running the code.
par(mfrow=c(1,2)) - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - hist() Expanded reference ↗
- Draw a Base R histogram. Check argument names and data types before running the code.
hist(x, main="...", xlab="...")
Concepts, learning goals and student instructions
What this teaches — concept breakdown
par(mfrow=c(1,2)) divides a base-R graphics device into two panels. The histograms compare distributions of resampled means at two sample sizes.
Compare the widths of the simulated mean distributions rather than only their centres. Repeated means based on ten values usually vary less than those based on four. Resampling one empirical sample cannot guarantee that it represents a wider population.
Step-by-step classroom instructions
- Arrange two Base R plots side by side using par().
- Plot the resampled means for samples of size four.
- Plot the resampled means for samples of size ten, then compare spreads.
Masterclass learning goals
Learning goal: Explain why the n=10 distribution is usually narrower.
Concept: Visual comparison of sampling distributions and mean precision.
Original task checklist
Task instructions — what the student must do
- Arrange two Base R plots side by side using par().
- Plot the resampled means for samples of size four.
- Plot the resampled means for samples of size ten, then compare spreads.
Instructor's teaching method and common pitfalls
Explain the change in spread without interpreting both panels as raw observations.
Common trap / interpretation warning
The two histograms need comparable axes if you want a strong visual claim about width.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
Compare the widths of the simulated mean distributions rather than only their centres. Repeated means based on ten values usually vary less than those based on four. Resampling one empirical sample cannot guarantee that it represents a wider population.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Arrange two Base R plots side by side using par().
# par(mfrow=
# Step 2. Plot the resampled means for samples of size four.
# hist(means_n4,
# Step 3. Plot the resampled means for samples of size ten, then compare spreads.
# hist(means_n10,Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Configure the base-R plotting layout.
par(mfrow=c(1,2))
# NOTE: Draw a histogram of the supplied numeric vector.
hist(means_n4,main="Resample size 4",xlab="Mean RT (ms)")
# NOTE: Draw a histogram of the supplied numeric vector.
hist(means_n10,main="Resample size 10",xlab="Mean RT (ms)")
# NOTE: Configure the base-R plotting layout.
par(mfrow=c(1,1))Expected output, excerpts and validation checks
[Plot] Two side-by-side resampled-mean histograms: n=4 and n=10.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
Hypothesis testing, confidence intervals and regression
Original Teacher's Kit — Week 6: teaching notes, alternative demonstration and line-by-line R analysis
Hypothesis testing, p-values and intervals — provisional
Define H0: μ=600 ms against a two-sided alternative; run a one-sample t-test and interpret p-value and CI with assumptions.
Expected output and interpretation
Fictional t-test: n=12, mean 606.75 ms, df=11, t≈2.263, two-sided p≈0.0448, and a 95% CI of roughly [600.185, 613.315] ms. This does not establish a meaningful population effect or representative sample.
Live demonstration
Have the student avoid interpreting p≈0.045 as the probability H0 is false. Discuss how the 95% CI excludes 600 and what assumptions this requires.
R script: line-by-line explanation
The table shows executable lines from the openly published, original solution. Continuation lines of multi-line calls are explained separately.
| R code | What exactly happens? |
|---|---|
01rt_ms <- c(620,610,590,605,615,600,625,595,608,612,598,603) | Uses the same 12 fictional response times as Week 5 for continuity. |
02reference_mu <- 600 # arbitrary teaching benchmark, not a research claim | 600 ms is an arbitrary teaching reference, not a hypothesis derived from an actual study. |
03result <- t.test(rt_ms, mu=reference_mu, alternative="two.sided") | t.test(x,mu=600,alternative='two.sided') performs a two-sided one-sample t-test of H0: μ=600 and returns a CI. |
04print(result) | print(result) displays t statistic, df, p-value, 95% CI and estimated mean. |
05print(c(estimate_ms=unname(result$estimate), t=unname(result$statistic), p=result$p.value)) | $estimate is the sample mean, $statistic is t, and $p.value is the p-value; unname() removes attached names. |
06print(result$conf.int) | $conf.int returns the confidence limits in milliseconds; it does not give a 95% posterior probability for this one interval. |
07stopifnot(result$parameter == length(rt_ms)-1, result$p.value>=0, | Degrees of freedom should be n−1; the p-value must lie between 0 and 1. |
08result$p.value<=1, length(result$conf.int)==2L) | Continuation of stopifnot(): checks valid p and two confidence interval endpoints. |
09cat("WEEK 6 WORKED EXAMPLE PASS\n") | cat() prints a code-check banner; substantive inference still depends on design and assumptions. |
Likely misconception
Independence and assumptions for the mean matter; n=12 is small. A p-value below .05 is not, by itself, scientific relevance or causal evidence.
Exit check
State H0/H1. The p-value is the probability of what? Explain 95% confidence in repeated sampling.
W6-E01 Null hypothesis and one-sample t test
MOODLE SOURCE NOTE: Independent ferdo Lab provisional lesson; no verified Moodle Week 6 file. INDEPENDENT ADDITION (not an official Moodle task).
R functions and syntax reference · 7 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- sqrt() Expanded reference ↗
- Calculate the non-negative square root. Check argument names and data types before running the code.
sqrt(x) - pt() Expanded reference ↗
- Evaluate the cumulative probability for a Student t distribution. For a two-sided t test, account for both tails of the distribution.
pt(t, df) - abs() Expanded reference ↗
- Return the absolute value of each number. Check argument names and data types before running the code.
abs(x) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - t.test() Expanded reference ↗
- Perform a Student t test and report a confidence interval. Check argument names and data types before running the code.
t.test(x, mu=600) - p-value Expanded reference ↗
- Compute the two-sided tail probability under the null model.
2 * pt(-abs(t), df)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
A one-sample t statistic compares the observed mean to hypothesised mu0 in units of estimated standard errors. t.test() also returns a p-value and confidence interval under modelling assumptions.
Under H0: μ=600 ms, the one-sample t statistic is (sample_mean−600)/(sample_SD/sqrt(n)) with df=n−1. The two-sided p value measures how extreme the observed statistic is under H0; it is not the probability that H0 is true.
Step-by-step classroom instructions
- Set the null-hypothesis population mean to 600 milliseconds.
- Calculate the one-sample t statistic from the observed mean, SD and n.
- Run t.test() against the same null hypothesis and compare the outputs.
Masterclass learning goals
Learning goal: Compute t manually, compare with t.test, interpret p and confidence interval.
Concept: Null hypothesis, t statistic, degrees of freedom and p value.
Original task checklist
Task instructions — what the student must do
- Set the null-hypothesis population mean to 600 milliseconds.
- Calculate the one-sample t statistic from the observed mean, SD and n.
- Run t.test() against the same null hypothesis and compare the outputs.
Instructor's teaching method and common pitfalls
Show t=(mean−mu0)/(SD/sqrt(n)) and why the degrees of freedom are n−1.
Common trap / interpretation warning
A small p-value does not establish substantive importance or guarantee the model's assumptions.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
Under H0: μ=600 ms, the one-sample t statistic is (sample_mean−600)/(sample_SD/sqrt(n)) with df=n−1. The two-sided p value measures how extreme the observed statistic is under H0; it is not the probability that H0 is true.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Set the null-hypothesis population mean to 600 milliseconds.
# mu0 <-
# Step 2. Calculate the one-sample t statistic from the observed mean, SD and n.
# t_manual <-
# Step 3. Run t.test() against the same null hypothesis and compare the outputs.
# model_t <- t.test(Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Assign the computed result to a named R object.
mu0 <- 600 # Hypothesised population mean, milliseconds.
# NOTE: Compute t from a mean difference divided by its standard error.
t_manual <- (rt_mean-mu0)/(rt_sd/sqrt(rt_n))
# NOTE: Assign the computed result to a named R object.
df_manual <- rt_n-1
# NOTE: Assign the computed result to a named R object.
two_sided_p <- 2*pt(-abs(t_manual),df=df_manual)
# NOTE: Show the result in the Console (or display a ggplot object).
print(c(t=t_manual,df=df_manual,p=two_sided_p))
# NOTE: Run a one-sample t test and request its confidence interval.
model_t <- t.test(rt_demo,mu=mu0,alternative="two.sided",conf.level=.95)
# NOTE: Show the result in the Console (or display a ggplot object).
print(model_t)Expected output, excerpts and validation checks
t ≈ 2.2631 df = 11 p ≈ 0.04484
# t.test() additionally prints the 95% confidence interval and sample mean.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W6-E02 Confidence interval and effect size
MOODLE SOURCE NOTE: Independent ferdo Lab provisional lesson. INDEPENDENT ADDITION (not an official Moodle task).
R functions and syntax reference · 6 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- qt() Expanded reference ↗
- Get a quantile (critical value) of a Student t distribution. For a two-sided 95% CI, the upper reference quantile is 0.975.
qt(.975, df) - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - stopifnot() Expanded reference ↗
- Stop execution with an error if a logical condition is not true. Check argument names and data types before running the code.
stopifnot(condition) - all.equal() Expanded reference ↗
- Compare objects approximately, allowing small numeric tolerances. Check argument names and data types before running the code.
all.equal(x, y) - as.numeric() Expanded reference ↗
- Convert values to numeric form when conversion is meaningful. Check argument names and data types before running the code.
as.numeric(x)
Concepts, learning goals and student instructions
What this teaches — concept breakdown
A t confidence interval uses the critical t quantile times the standard error. Cohen's d scales the observed difference from mu0 by sample SD; all.equal() checks numerical agreement with t.test().
A two-sided 95% t confidence interval is sample_mean ± t_critical × SE. It combines sample variability, sample size and a t quantile. Cohen’s d standardises the observed mean difference relative to sample SD; practical importance and statistical significance are distinct.
Step-by-step classroom instructions
- Find the critical t value for a two-sided 95% confidence interval.
- Calculate the confidence interval manually from the sample mean and SE.
- Calculate Cohen’s d to describe standardised effect size.
Masterclass learning goals
Learning goal: Check 95% t interval, and distinguish statistical and practical significance.
Concept: A 95% t confidence interval, effect size and practical significance.
Original task checklist
Task instructions — what the student must do
- Find the critical t value for a two-sided 95% confidence interval.
- Calculate the confidence interval manually from the sample mean and SE.
- Calculate Cohen’s d to describe standardised effect size.
Instructor's teaching method and common pitfalls
Contrast an interval for a population mean with an interval for individual trials.
Common trap / interpretation warning
An interval describes uncertainty about a mean under assumptions, not a probability that individual scores lie inside it.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
A two-sided 95% t confidence interval is sample_mean ± t_critical × SE. It combines sample variability, sample size and a t quantile. Cohen’s d standardises the observed mean difference relative to sample SD; practical importance and statistical significance are distinct.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Find the critical t value for a two-sided 95% confidence interval.
# critical_t <- qt(
# Step 2. Calculate the confidence interval manually from the sample mean and SE.
# ci_manual <-
# Step 3. Calculate Cohen’s d to describe standardised effect size.
# cohens_d <-Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Assign the computed result to a named R object.
critical_t <- qt(.975,df=rt_n-1)
# NOTE: Construct the t interval as mean ± critical t × SE.
ci_manual <- rt_mean + c(-1,1)*critical_t*rt_se
# NOTE: Standardise the mean difference using the sample SD.
cohens_d <- (rt_mean-mu0)/rt_sd
# NOTE: Show the result in the Console (or display a ggplot object).
print(c(ci_lower=ci_manual[1],ci_upper=ci_manual[2],cohens_d=cohens_d))
# NOTE: Assert that a data-quality or numerical check is true; stop on failure.
stopifnot(isTRUE(all.equal(as.numeric(ci_manual),as.numeric(model_t$conf.int),tolerance=1e-8)))Expected output, excerpts and validation checks
ci_lower ≈ 600.1854
ci_upper ≈ 613.3146
cohens_d ≈ 0.6533
# stopifnot() prints nothing if the two CI calculations agree.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.
W6-E03 Regression, correlation, model diagnostics
MOODLE SOURCE NOTE: Independent ferdo Lab enrichment; not a verified Moodle Week 6 worksheet. INDEPENDENT ADDITION (not an official Moodle task).
R functions and syntax reference · 5 entries · local deep links
These expanded syntax notes are a first-class part of every exercise. Select a function name for a dedicated, self-hosted reference article.
- lm() Expanded reference ↗
- Fit a linear statistical model using a formula. A simple linear model requires careful checks of its assumptions.
lm(y ~ x, data=data) - print() Expanded reference ↗
- Display an object or calculated value in the R Console. Printing does not change the object being displayed.
print(x) - summary() Expanded reference ↗
- Show a descriptive or model-specific statistical summary. Check argument names and data types before running the code.
summary(model) - c() Expanded reference ↗
- Combine multiple values into a vector. Mixed types may be coerced to a single common type.
c(a, b, ...) - cor() Expanded reference ↗
- Calculate a correlation coefficient, Pearson by default. Correlation does not establish causation.
cor(x, y, use="complete.obs")
Concepts, learning goals and student instructions
What this teaches — concept breakdown
lm() estimates a linear relationship between CES-D and AHI. Coefficients, correlation r and R² summarise an association; repeated measures violate a simple independent-row assumption.
A linear-regression slope estimates the expected change in a response for a one-unit increase in a predictor, conditional on the model. Inspect residual patterns and independence assumptions. Repeated records for one participant are not independent, so a simple model here is only a mechanical illustration.
Step-by-step classroom instructions
- Fit a linear regression model predicting one variable from another.
- Print the model summary, including coefficients and R-squared.
- Print the correlation coefficient for comparison with the regression.
Masterclass learning goals
Learning goal: Interpret slope, R^2; explain confounding and dependence from repeated observations.
Concept: Linear regression, model coefficients, R-squared and assumptions.
Original task checklist
Task instructions — what the student must do
- Fit a linear regression model predicting one variable from another.
- Print the model summary, including coefficients and R-squared.
- Print the correlation coefficient for comparison with the regression.
Instructor's teaching method and common pitfalls
Ask which variable is outcome and which is predictor, then evaluate whether the observations can be considered independent.
Common trap / interpretation warning
Do not treat this basic repeated-record model as a causal or fully valid independent-observation analysis.
Concept explanation and statistical interpretation
Concept explanation and statistical interpretation
A linear-regression slope estimates the expected change in a response for a one-unit increase in a predictor, conditional on the model. Inspect residual patterns and independence assumptions. Repeated records for one participant are not independent, so a simple model here is only a mechanical illustration.
Student starter — deliberately incomplete
Student workbook: instructions and unfinished code
Each commented prefix corresponds to the step above. Remove #, finish the expression, and run that line in RStudio.
# Step 1. Fit a linear regression model predicting one variable from another.
# fit <- lm(
# Step 2. Print the model summary, including coefficients and R-squared.
# print(summary(
# Step 3. Print the correlation coefficient for comparison with the regression.
# print(c(r=Instructor: completed R solution, line-by-line comments
Complete original executable statements; newly added comment lines explain the operations. Move code to RStudio with the linked package’s data/ folder.
# NOTE: Fit an ordinary least-squares linear model.
fit <- lm(cesdTotal~ahiTotal,data=all_data)
# NOTE: Show the result in the Console (or display a ggplot object).
print(summary(fit)$coefficients)
# NOTE: Show the result in the Console (or display a ggplot object).
print(c(r=cor(all_data$ahiTotal,all_data$cesdTotal),
# NOTE: Continue this R expression with its arguments, values or formatting.
r_squared=summary(fit)$r.squared))
# Assumptions: independence, approximately linear relationship, conditional errors.
# END OF THE SIX-WEEK COURSE.Expected output, excerpts and validation checks
Estimate Std. Error t value Pr(>|t|)
(Intercept) ... ... ... ...
ahiTotal ... ... ... ...
r = ... ; r_squared = ...
# Coefficient values depend on the public dataset.Data-dependent results are deliberately given as schemas or previews. Only deterministic outputs are numerically specified; no R runtime test is claimed for this page.