← Course home
MODULE 11 · FIRST-YEAR LEVEL

Categorical data and chi-square analysis

Are two categorical variables associated?

70–90 minutesConcepts first, R optionalSynthetic data

Learning outcomes

Conceptual lesson

Summarise categories using frequency tables and row or column percentages. Pearson's chi-square test of independence compares observed cell counts with expected counts under independence. The denominator chosen for a percentage changes its interpretation.

The approximation depends on independent observations and sufficiently large expected cell counts. Fisher's exact test can be considered for sparse 2×2 tables. Do not automatically trust an approximate chi-square p-value when expected counts are small. A general r×c contingency table has (r−1)(c−1) degrees of freedom.

A magnitude measure such as Cramér's V can supplement a p-value. Interpret percentages conditionally on the research question; a significant chi-square test does not establish which mechanism produced the association.

Worked research example

Cross-tabulate A/B/C group labels and Visual/Text preferences in the fictional dataset. Compare percentages within each group, then inspect the chi-square test. Neither group membership nor preference can be interpreted causally.

Common reasoning trap

Confusing a percentage out of the full sample with a percentage within a group changes what the table says.

Independent practice

  1. Create a group-by-preference contingency table and group-wise percentages.
  2. Check expected frequencies and interpret the chi-square test with its conditions.
  3. Describe any association without making a causal claim.

Explain your reasoning, not only the number.

Optional R lab

Save the synthetic CSV in the working folder before running the script. Base R only.

CSV · Download R script

# Statistics Lab / ferdo — synthetic data (no real student records)
# Save stats_synthetic.csv in your working directory.
d <- read.csv("stats_synthetic.csv", stringsAsFactors = TRUE)
stopifnot(nrow(d) == 36, all(c("score_pre","score_post","group") %in% names(d)))
# Groups are observational labels: differences cannot establish a treatment effect.

tab <- table(d$group, d$preference)
tab
prop.table(tab, margin=1)
test <- chisq.test(tab)
test$expected
test
# Chi-square p-values can be unreliable with small expected counts.

Stretch: mathematical track

Distinguish odds ratios from risk ratios in a 2×2 table.

Exit ticket

Write one defensible claim and one limitation from this week's example.

Student workbook and self-check

Four first-year written problems, 20-mark rubric and a four-question self-check.

Open week 11 workbook →