ferdo Lab · independently merged instructor resource

Ultimate Instructor's Kit

Six weeks, 38 exercises, the original Teacher's Kit pedagogy, step-by-step student tasks, deeply annotated completed R code, expected outputs, and a prominent self-hosted functions and syntax reference.

Open local R Functions & Syntax ReferenceAnnotated instructor .R scriptDownload existing course data ZIP

Instructor dashboard and methodology

Two editions merged: the original Teacher's Kit’s weekly teaching notes and line-by-line historical demonstrations, plus the Superpowered Kit’s 38 annotated tasks, outputs and common pitfalls. All lesson-specific R functions are given prominence.

90-minute teaching flow and pre-session checklist

How to teach (90 minutes)

  1. 00–10 · Diagnose: two predictions from prior work, paths and R setup.
  2. 10–25 · Concepts and data dictionary: variable meaning and units.
  3. 25–45 · Live R: predict, run, explain output.
  4. 45–65 · Independent student TODO tasks; instructor offers hints.
  5. 65–80 · Debugging, inference limits and counterexample.
  6. 80–90 · Three-question exit ticket and next homework.

Before each session

  • Working directory: package root containing data/ for Weeks 1–4; Weeks 5–6 scripts are standalone.
  • Required packages: base R; any dplyr/ggplot2 mapping to original Moodle work is additional.
  • Student attempts TODO starter first; instructor keeps the worked script separate.
  • Use RStudio Run line by line; the final PASS line indicates only local assertions.
  • Revisit distribution versus association versus causality, and sample versus population.
  • Use your browser's Print function to save this self-contained page as a PDF.
Data and source differences across editions

The older weekly Teacher's Kit includes historical fictional examples, often using different toy CSVs, variable names and row counts than the six-week Masterclass. Those weekly worked examples are preserved as alternative teaching demonstrations — their numeric results must not be compared as if they came from the same dataset. Each of the 38 exercise panels below follows the newer Masterclass task and annotated solutions.

Weeks 1–4: independently rewritten exercises aligned with supplied Moodle materials. Weeks 5–6: separate ferdo Lab extensions (not verified Moodle assignments). The definitive UCL module enrolment code remains unconfirmed. The public datasets are fictional.

The specific RPubs page PALS0046 R Cheatsheet by Metodi Siromahov was not present in the available private Moodle ZIP. The linked reference here is a newly assembled, locally hosted ferdo Lab reference, not an unauthorised copy of the RPubs document.

Local reference strategy. Original PALS0046 RPubs cheatsheet not found among the 21 files in the current private Moodle ZIP. Rather than imply a mirror exists, all function links point to a new original ferdo Lab reference, built from our own course explanations, with 76 directly linkable entries. The original resource is credited there as related background, not copied.
38 / 38 tasks
Week 1 · 7 exercises

R basics, vectors and inspection

Rewritten exercises aligned with supplied Week 1–4 Moodle tasks; some E exercises are independent extensions.

Original Teacher's Kit — Week 1: teaching notes, alternative demonstration and line-by-line R analysis
W0116 R lines annotated

R basics and data frames

Students distinguish Console and script and explain objects, vectors, indexing, CSV import and data-frame operations.

Expected output and interpretation

Reference checks: 7+5=12; 3×(4+2)=18; x has length 4, mean 9, second element 8, and x>8 selects 10 and 12. The fictional dataset has 12 rows; mean age ≈21.17.

Live demonstration

Ask for predictions of x[2] and x[x>8] before running. Then demonstrate the distinction between p and p$age.

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 codeWhat exactly happens?
01print(7+5)print() displays the evaluated expression in the Console; 7+5=12.
02print(3*(4+2))The parentheses evaluate 4+2 before multiplication, giving 18.
03x <- c(6,8,10,12)c() combines four numbers into one numeric vector; <- assigns it to x.
04print(length(x))length() returns the number of elements, which is 4 here, not their sum.
05print(mean(x))mean() computes the arithmetic average; (6+8+10+12)/4 = 9.
06print(x[2])Square brackets select by position; R's second element x[2] is 8.
07print(x[x>8])x>8 creates a TRUE/FALSE mask, which selects only 10 and 12.
08p <- read.csv("data/participants.csv")Loads the CSV into data frame p. The working directory must be the parent of data/.
09print(head(p))head(p) displays the first six rows by default; it does not verify all column types.
10str(p)str(p) inspects dimensions and the R class of each column.
11print(nrow(p))nrow(p) counts rows/observations; the expected value is 12 fictional records.
12print(mean(p$age))$age extracts the age column from p and mean() averages that vector.
13print(aggregate(age~intervention,p,mean))age~intervention groups ages by intervention for descriptive mean summaries only.
14plot(seq_len(nrow(p)),p$age,pch=19,xlab="Fictional row",ylab="Age",main="Synthetic participants")seq_len(nrow(p)) makes row indices 1–12; pch=19 draws solid points, and xlab/ylab name axes.
15stopifnot(length(x)==4L,mean(x)==9,nrow(p)==12L)stopifnot() asserts all conditions are TRUE and stops with an error if one fails.
16cat("W1 PASS: 12 synthetic participants, no external packages\n")cat() prints a status message; the message is not validation of real-world research.

Likely misconception

R indexing starts at 1; p$age is a column vector; plotting row order does not imply an experiment or causality.

Exit check

Exit questions: What does read.csv() return? What does str() inspect? Can 12 convenience records support population claims?

W1-M01 R as calculator · R syntax: print()

MOODLE SOURCE NOTE: pr01. Familiarisation (3).r · task 1. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Add 6 and 1, then print the result.
  2. Multiply 2 by the sum of 1 and 3, then print the result.
  3. 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

  1. Add 6 and 1, then print the result.
  2. Multiply 2 by the sum of 1 and 3, then print the result.
  3. 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
Exact, deterministic example. Use the unmodified example code for comparison.
[1] 7
[1] 8
[1] 11

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-M02 Assignment and reusable results · R syntax: sum(), print(), ls(), <-

MOODLE SOURCE NOTE: pr01. Familiarisation (3).r · task 2. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Add the integers from 1 to 10 and store the total in x.
  2. 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

  1. Add the integers from 1 to 10 and store the total in x.
  2. 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
Exact values where deterministic; otherwise preview. Use the unmodified example code for comparison.
[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.

Reference links:sum() · print() · ls() · <- · Masterclass original task
W1-M03 Text, numbers, vectors and indexing · R syntax: c(), print(), mean(), [ ]

MOODLE SOURCE NOTE: pr01. Familiarisation (3).r · task 3 and naming notes. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Store a short text label in course_label.
  2. Store the number of participants as an integer in participants.
  3. Create a numeric vector containing four fictional sleep durations.
  4. 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

  1. Store a short text label in course_label.
  2. Store the number of participants as an integer in participants.
  3. Create a numeric vector containing four fictional sleep durations.
  4. 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
Exact, deterministic example. Use the unmodified example code for comparison.
[1] 6
[1] 8 7
[1] 6.5

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.

Reference links:c() · print() · mean() · [ ] · Masterclass original task
W1-M04 Built-in USArrests data frame · R syntax: print(), dim(), names(), head()

MOODLE SOURCE NOTE: pr01. Familiarisation (3).r · task 5. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Assign the built-in USArrests dataset to an object called crime.
  2. Print the number of rows and columns in crime.
  3. Print all column names in crime.
  4. 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

  1. Assign the built-in USArrests dataset to an object called crime.
  2. Print the number of rows and columns in crime.
  3. Print all column names in crime.
  4. 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
Exact values where deterministic; otherwise preview. Use the unmodified example code for comparison.
[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 · R syntax: print(), max(), c()

MOODLE SOURCE NOTE: pr01. Familiarisation (3).r · tasks 6–8. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Print the maximum value in the Murder column of crime.
  2. Print the Assault column (or a relevant element of it) using the dollar operator.
  3. 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

  1. Print the maximum value in the Murder column of crime.
  2. Print the Assault column (or a relevant element of it) using the dollar operator.
  3. 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
Exact values where deterministic; otherwise preview. Use the unmodified example code for comparison.
[1] 6
# print(crime$Murder) shows all 50 values (truncated here).
[1] 17.4
[1] 337

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.

Reference links:print() · max() · c() · Masterclass original task
W1-M06 Removing objects · R syntax: rm(), print(), exists()

MOODLE SOURCE NOTE: pr01. Familiarisation (3).r · task 9. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Remove the crime object from the current R environment.
  2. 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

  1. Remove the crime object from the current R environment.
  2. 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
Exact, deterministic example. Use the unmodified example code for comparison.
[1] FALSE

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-E01 Additional: reproducible report · R syntax: c(), print(), data.frame(), seq_along()

MOODLE SOURCE NOTE: ferdo Lab original extension. INDEPENDENT ADDITION (not an official Moodle task).

Includes independent ferdo Lab teaching material
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

  1. Write a fictional research question and store it as a text value.
  2. Create a short numeric vector of fictional reaction times.
  3. 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

  1. Write a fictional research question and store it as a text value.
  2. Create a short numeric vector of fictional reaction times.
  3. 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
Exact, deterministic example. Use the unmodified example code for comparison.
  trial rt_ms
1     1   620
2     2   610
3     3   590
4     4   605

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.

Week 2 · 10 exercises

Data wrangling, joins and paired differences

Rewritten exercises aligned with supplied Week 1–4 Moodle tasks; some E exercises are independent extensions.

Original Teacher's Kit — Week 2: teaching notes, alternative demonstration and line-by-line R analysis
W0216 R lines annotated

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 codeWhat 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$prepost-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 · R syntax: read.csv(), print(), c(), nrow()

MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part A tasks 1–2. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Import data/participant-info.csv as the data frame pinfo.
  2. Import data/ahi-cesd.csv as the data frame responses.
  3. 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

  1. Import data/participant-info.csv as the data frame pinfo.
  2. Import data/ahi-cesd.csv as the data frame responses.
  3. 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
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 · R syntax: inner_join(), c(), print(), nrow(), n_distinct(), stopifnot()

MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part A task 3. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Join participant information and responses by both id and intervention.
  2. 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

  1. Join participant information and responses by both id and intervention.
  2. 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
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 · R syntax: select(), print(), names()

MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part B select. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Select the required analysis columns without removing any rows.
  2. 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

  1. Select the required analysis columns without removing any rows.
  2. 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
Exact, deterministic example. Use the unmodified example code for comparison.
[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 · R syntax: filter(), c(), print(), table(), %in%

MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part B filter, compared with code-book.pdf. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Keep only observations at baseline (occasion 0) and posttest (occasion 1).
  2. 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

  1. Keep only observations at baseline (occasion 0) and posttest (occasion 1).
  2. 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
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.

Reference links:filter() · c() · print() · table() · %in% · Masterclass original task
W2-M05 arrange(): rows · R syntax: arrange(), print(), head(), select()

MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part B arrange. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Sort the selected observations by ahiTotal from low to high.
  2. 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

  1. Sort the selected observations by ahiTotal from low to high.
  2. 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
  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 · R syntax: summarise(), n(), mean(), print()

MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part B summarise. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Calculate overall average AHI and CES-D scores in one summary row.
  2. 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

  1. Calculate overall average AHI and CES-D scores in one summary row.
  2. 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_summary
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: 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
  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 · R syntax: group_by(), summarise(), n(), mean(), print(), |>

MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part B group_by. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Start a pipe to summarise the sorted pre/post observations.
  2. Group the piped observations by occasion.
  3. 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

  1. Start a pipe to summarise the sorted pre/post observations.
  2. Group the piped observations by occasion.
  3. 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
  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 · R syntax: mutate(), print(), head(), select()

MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part B mutate. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Create a new sadness column by subtracting ahiTotal from cesdTotal.
  2. 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

  1. Create a new sadness column by subtracting ahiTotal from cesdTotal.
  2. 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
  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 · R syntax: mutate(), factor(), c(), print(), table()

MOODLE SOURCE NOTE: pr02. Data Wrangling.r · Part B recode, compared with code-book.pdf. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Add a correctly labelled sex variable to the pre/post data frame.
  2. 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

  1. Add a correctly labelled sex variable to the pre/post data frame.
  2. 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
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 · R syntax: filter(), select(), inner_join(), c(), mutate(), print(), summarise(), n(), mean()

MOODLE SOURCE NOTE: ferdo Lab original extension. INDEPENDENT ADDITION (not an official Moodle task).

Includes independent ferdo Lab teaching material
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

  1. Filter baseline records for participants observed before the intervention.
  2. Filter posttest records for participants observed after the intervention.
  3. 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

  1. Filter baseline records for participants observed before the intervention.
  2. Filter posttest records for participants observed after the intervention.
  3. 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
  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.

Week 3 · 8 exercises

AQ-10 scoring and descriptive statistics

Rewritten exercises aligned with supplied Week 1–4 Moodle tasks; some E exercises are independent extensions.

Original Teacher's Kit — Week 3: teaching notes, alternative demonstration and line-by-line R analysis
W0317 R lines annotated

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 codeWhat 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) <- NULLRemoves 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 · R syntax: read.csv(), print(), c(), nrow()

MOODLE SOURCE NOTE: wk3_practical_summarising_data (1).r · Part A task 1. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Read the question-format lookup file from the data folder.
  2. Read the scoring-key lookup file from the data folder.
  3. 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

  1. Read the question-format lookup file from the data folder.
  2. Read the scoring-key lookup file from the data folder.
  3. 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
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 · R syntax: pivot_longer(), all_of(), paste0(), print(), dim()

MOODLE SOURCE NOTE: wk3_practical_summarising_data (1).r · Part A task 2. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Start turning the wide AQ response table into a long table.
  2. 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

  1. Start turning the wide AQ response table into a long table.
  2. 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
[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 · R syntax: inner_join(), c(), stopifnot(), nrow(), anyNA(), print(), head(), select()

MOODLE SOURCE NOTE: wk3_practical_summarising_data (1).r · Part A task 3. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Join each long-format AQ response with its forward/reverse item direction.
  2. 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

  1. Join each long-format AQ response with its forward/reverse item direction.
  2. 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
  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 · R syntax: group_by(), summarise(), sum(), stopifnot(), all(), print(), head()

MOODLE SOURCE NOTE: wk3_practical_summarising_data (1).r · Part A task 4. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Begin a pipe that calculates a total AQ-10 score for each participant.
  2. Group the scored questionnaire rows by participant ID.
  3. 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

  1. Begin a pipe that calculates a total AQ-10 score for each participant.
  2. Group the scored questionnaire rows by participant ID.
  3. 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
  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 · R syntax: pivot_longer(), all_of(), paste0(), inner_join(), c(), group_by(), summarise(), sum(), stopifnot(), identical(), |>

MOODLE SOURCE NOTE: wk3_practical_summarising_data (1).r · Part B pipe. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Start a single piped workflow using the original AQ response table.
  2. Reshape Q1–Q10 from wide to long format in the pipeline.
  3. 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

  1. Start a single piped workflow using the original AQ response table.
  2. Reshape Q1–Q10 from wide to long format in the pipeline.
  3. 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
Exact, deterministic example. Use the unmodified example code for comparison.
# 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 · R syntax: summarise(), n(), mean(), sd(), min(), max(), sum(), print(), filter()

MOODLE SOURCE NOTE: wk3_practical_summarising_data (1).r · Part C tasks 1–3. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Calculate the mean, standard deviation and range of AQ totals.
  2. 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

  1. Calculate the mean, standard deviation and range of AQ totals.
  2. 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_summary
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: 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
  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.

Reference links:summarise() · n() · mean() · sd() · min() · max() · sum() · print() · Masterclass original task
W3-M07 AQ frequency histogram · R syntax: ggplot(), aes(), geom_histogram(), scale_x_continuous(), theme_classic(), labs(), print()

MOODLE SOURCE NOTE: wk3_practical_summarising_data (1).r · Part C final histogram. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Define a ggplot object for the AQ total-score distribution.
  2. Add a histogram layer with a bin width of one point.
  3. 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

  1. Define a ggplot object for the AQ total-score distribution.
  2. Add a histogram layer with a bin width of one point.
  3. 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_aq
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_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
Expected visual output. A graphical result is expected; no fabricated raster image.
[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 · R syntax: var(), sd(), sqrt(), nrow(), print(), c()

MOODLE SOURCE NOTE: ferdo Lab original extension. INDEPENDENT ADDITION (not an official Moodle task).

Includes independent ferdo Lab teaching material
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

  1. Compute the sample variance of the AQ total scores.
  2. Compute the standard error using SD divided by the square root of n.
  3. 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

  1. Compute the sample variance of the AQ total scores.
  2. Compute the standard error using SD divided by the square root of n.
  3. 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
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.

Reference links:var() · sd() · sqrt() · nrow() · print() · c() · Masterclass original task
Week 4 · 7 exercises

Visualisation with ggplot2

Rewritten exercises aligned with supplied Week 1–4 Moodle tasks; some E exercises are independent extensions.

Original Teacher's Kit — Week 4: teaching notes, alternative demonstration and line-by-line R analysis
W0412 R lines annotated

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 codeWhat 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 · R syntax: ggplot(), aes(), geom_histogram(), labs(), print(), +

MOODLE SOURCE NOTE: wk4_practical_visualisation.r · Part 1 histogram. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Start a ggplot of the distribution of AHI scores.
  2. Add a histogram with a chosen bin width, then compare alternatives.
  3. 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

  1. Start a ggplot of the distribution of AHI scores.
  2. Add a histogram with a chosen bin width, then compare alternatives.
  3. 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_hist
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_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
Expected visual output. A graphical result is expected; no fabricated raster image.
[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 · R syntax: mutate(), factor(), c(), ggplot(), aes(), geom_point(), labs(), print()

MOODLE SOURCE NOTE: wk4_practical_visualisation.r · Part 1 scatterplot. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Create meaningful factor labels for the sex variable using the codebook.
  2. 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

  1. Create meaningful factor labels for the sex variable using the codebook.
  2. 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
Expected visual output. A graphical result is expected; no fabricated raster image.
[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 · R syntax: ggplot(), aes(), factor(), geom_boxplot(), labs(), print(), geom_violin(), geom_jitter()

MOODLE SOURCE NOTE: wk4_practical_visualisation.r · Part 1 box/violin. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Create a ggplot object that compares the outcome across groups.
  2. Add a boxplot layer to display medians and quartiles.
  3. 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

  1. Create a ggplot object that compares the outcome across groups.
  2. Add a boxplot layer to display medians and quartiles.
  3. 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
Expected visual output. A graphical result is expected; no fabricated raster image.
[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 · R syntax: mutate(), factor(), group_by(), summarise(), mean(), ggplot(), aes(), geom_col(), n(), sd(), |>

MOODLE SOURCE NOTE: wk4_practical_visualisation.r · Part 1 bar plot. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Create readable labels for the intervention groups.
  2. Start a pipeline from the full data to calculate group means.
  3. Group the data by intervention before calculating each mean.
  4. 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

  1. Create readable labels for the intervention groups.
  2. Start a pipeline from the full data to calculate group means.
  3. Group the data by intervention before calculating each mean.
  4. 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
Expected visual output. A graphical result is expected; no fabricated raster image.
[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 · R syntax: ggplot(), aes(), geom_line(), geom_point(), geom_errorbar(), coord_cartesian(), c(), labs(), print()

MOODLE SOURCE NOTE: wk4_practical_visualisation.r · Part 1 line + ylim + SD. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Start a plot of group mean scores across measurement occasions.
  2. Add a line layer connecting the occasion means.
  3. 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

  1. Start a plot of group mean scores across measurement occasions.
  2. Add a line layer connecting the occasion means.
  3. 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
Expected visual output. A graphical result is expected; no fabricated raster image.
[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 · R syntax: print(), theme_classic(), labs(), theme_bw(), facet_wrap(), ggplot(), aes(), geom_point()

MOODLE SOURCE NOTE: wk4_practical_visualisation.r · Part 2 themes / labels / facet / size-shape-colour. VERIFIED W1-4 MOODLE TASK ALIGNMENT (rewritten solution).

Aligned to student-supplied Week 1–4 Moodle exercises
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

  1. Print the existing scatterplot using a classic ggplot theme.
  2. 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

  1. Print the existing scatterplot using a classic ggplot theme.
  2. 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
Expected visual output. A graphical result is expected; no fabricated raster image.
[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 · R syntax: cor(), print(), c(), read.csv(), inner_join(), nrow()

MOODLE SOURCE NOTE: ferdo Lab original extension; ATSQ file is separate from original W4 plot tasks. INDEPENDENT ADDITION (not an official Moodle task).

Includes independent ferdo Lab teaching material
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

  1. Calculate the correlation between AHI and CES-D with missing-data handling.
  2. Import the separately supplied ATSQ scores as a data frame.
  3. 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

  1. Calculate the correlation between AHI and CES-D with missing-data handling.
  2. Import the separately supplied ATSQ scores as a data frame.
  3. 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
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.

Week 5 · 3 exercises

Sampling and bootstrap simulations

Independent ferdo Lab supplemental teaching; not verified Moodle tasks.

Original Teacher's Kit — Week 5: teaching notes, alternative demonstration and line-by-line R analysis
W05 · PROVISIONAL19 R lines annotated

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 codeWhat 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 · R syntax: c(), length(), mean(), sd(), sqrt(), print()

MOODLE SOURCE NOTE: Independent ferdo Lab provisional lesson; no verified Moodle Week 5 file. INDEPENDENT ADDITION (not an official Moodle task).

Includes independent ferdo Lab teaching material
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

  1. Create a short fictional sample of reaction times in milliseconds.
  2. Calculate how many reaction times are in the sample.
  3. 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

  1. Create a short fictional sample of reaction times in milliseconds.
  2. Calculate how many reaction times are in the sample.
  3. 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
Exact, deterministic example. Use the unmodified example code for comparison.
n = 12
mean_ms = 606.75
sd_ms ≈ 10.3320
se_ms ≈ 2.9826

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.

Reference links:c() · length() · mean() · sd() · sqrt() · print() · Masterclass original task
W5-E02 Resampling and bootstrap percentile interval · R syntax: set.seed(), replicate(), mean(), sample(), print(), c(), sd(), quantile(), replace=TRUE

MOODLE SOURCE NOTE: Independent ferdo Lab provisional lesson; no verified Moodle Week 5 file. INDEPENDENT ADDITION (not an official Moodle task).

Includes independent ferdo Lab teaching material
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

  1. Set the random seed so the resampling results can be reproduced.
  2. Simulate 1,000 resampled means using a sample size of four.
  3. Simulate 1,000 resampled means using a sample size of ten.
  4. 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

  1. Set the random seed so the resampling results can be reproduced.
  2. Simulate 1,000 resampled means using a sample size of four.
  3. Simulate 1,000 resampled means using a sample size of ten.
  4. 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
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 · R syntax: par(), c(), hist()

MOODLE SOURCE NOTE: Independent ferdo Lab provisional lesson. INDEPENDENT ADDITION (not an official Moodle task).

Includes independent ferdo Lab teaching material
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

  1. Arrange two Base R plots side by side using par().
  2. Plot the resampled means for samples of size four.
  3. 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

  1. Arrange two Base R plots side by side using par().
  2. Plot the resampled means for samples of size four.
  3. 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
Expected visual output. A graphical result is expected; no fabricated raster image.
[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.

Reference links:par() · c() · hist() · Masterclass original task
Week 6 · 3 exercises

Hypothesis testing, confidence intervals and regression

Independent ferdo Lab supplemental teaching; not verified Moodle tasks.

Original Teacher's Kit — Week 6: teaching notes, alternative demonstration and line-by-line R analysis
W06 · PROVISIONAL9 R lines annotated

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 codeWhat 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 claim600 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 · R syntax: sqrt(), pt(), abs(), print(), c(), t.test(), p-value

MOODLE SOURCE NOTE: Independent ferdo Lab provisional lesson; no verified Moodle Week 6 file. INDEPENDENT ADDITION (not an official Moodle task).

Includes independent ferdo Lab teaching material
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

  1. Set the null-hypothesis population mean to 600 milliseconds.
  2. Calculate the one-sample t statistic from the observed mean, SD and n.
  3. 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

  1. Set the null-hypothesis population mean to 600 milliseconds.
  2. Calculate the one-sample t statistic from the observed mean, SD and n.
  3. 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
Exact values where deterministic; otherwise preview. Use the unmodified example code for comparison.
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.

Reference links:sqrt() · pt() · abs() · print() · c() · t.test() · p-value · Masterclass original task
W6-E02 Confidence interval and effect size · R syntax: qt(), c(), print(), stopifnot(), all.equal(), as.numeric()

MOODLE SOURCE NOTE: Independent ferdo Lab provisional lesson. INDEPENDENT ADDITION (not an official Moodle task).

Includes independent ferdo Lab teaching material
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

  1. Find the critical t value for a two-sided 95% confidence interval.
  2. Calculate the confidence interval manually from the sample mean and SE.
  3. 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

  1. Find the critical t value for a two-sided 95% confidence interval.
  2. Calculate the confidence interval manually from the sample mean and SE.
  3. 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
Exact values where deterministic; otherwise preview. Use the unmodified example code for comparison.
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 · R syntax: lm(), print(), summary(), c(), cor()

MOODLE SOURCE NOTE: Independent ferdo Lab enrichment; not a verified Moodle Week 6 worksheet. INDEPENDENT ADDITION (not an official Moodle task).

Includes independent ferdo Lab teaching material
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

  1. Fit a linear regression model predicting one variable from another.
  2. Print the model summary, including coefficients and R-squared.
  3. 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

  1. Fit a linear regression model predicting one variable from another.
  2. Print the model summary, including coefficients and R-squared.
  3. 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
Output format / checks (not fabricated values). Data-dependent: column layouts, placeholders or constraints only.
               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.

Reference links:lm() · print() · summary() · c() · cor() · Masterclass original task