Testing if Data Matches Expected Distributions
By the end of this module, you will be able to:
chisq.test() in R with specified expected proportionsA goodness-of-fit test answers the question:
"Does my observed data fit an expected pattern?"
Key characteristics:
Research Question: Do rats have equal preference for three maze arms?
Setup: Test 60 rats, each chooses one of three arms (Left, Center, Right)
Null Hypothesis (H₀): Rats choose arms equally (33.3% each)
Expected frequencies: 20 rats per arm (60 ÷ 3 = 20)
| Maze Arm | Observed | Expected |
|---|---|---|
| Left | 15 | 20 |
| Center | 18 | 20 |
| Right | 27 | 20 |
| Total | 60 | 60 |
Chi-square asks: Is the difference between observed (15, 18, 27) and expected (20, 20, 20) statistically significant, or just random variation?
Null Hypothesis (H₀): The observed distribution matches the expected distribution
Alternative Hypothesis (H₁): The observed distribution differs from the expected distribution
Unlike t-tests or ANOVA, Chi-square goodness-of-fit is non-directional. We don't predict which category will be higher - just that the pattern differs from expectation.
| Expected Pattern | When to Use | Example |
|---|---|---|
| Equal proportions | Testing if all categories are equally likely | Coin flips (50/50), die rolls (1/6 each) |
| Specified ratios | Testing Mendelian ratios, known distributions | Genetics (3:1 ratio), survey norms |
| Population proportions | Comparing sample to known population | Census data, disease prevalence |
Where:
Interpretation: Larger χ² values = bigger difference between observed and expected = more evidence against H₀
Calculate χ² by hand to understand how it works!
| Category | Observed (O) | Expected (E) | (O-E)²/E |
|---|---|---|---|
| Category 1 | - | ||
| Category 2 | - | ||
| Category 3 | - |
Now let's run this analysis in R! The function is chisq.test().
# Vector of observed frequencies
observed <- c(15, 18, 27)
# Give them meaningful names
names(observed) <- c("Left", "Center", "Right")
# Check your data
observed
# Test against equal proportions (default)
chisq.test(observed)
# OR specify custom expected proportions
# For equal: p = c(1/3, 1/3, 1/3)
chisq.test(observed, p = c(1/3, 1/3, 1/3))
Chi-squared test for given probabilities
data: observed
X-squared = 4.3, df = 2, p-value = 0.1165
What this output tells you:
Interpretation: p = 0.117 > 0.05, so we fail to reject H₀. The observed distribution doesn't significantly differ from equal proportions. Rats don't show a clear preference.
k = number of categories
Why k - 1? Once you know the frequencies in (k-1) categories and the total n, the last category is determined. That's one constraint, so we lose one degree of freedom.
Examples:
Always create a bar plot to visualize observed vs. expected frequencies!
# Create a bar plot comparing observed and expected
observed <- c(15, 18, 27)
expected <- c(20, 20, 20)
categories <- c("Left", "Center", "Right")
# Combine into a matrix for plotting
data <- rbind(observed, expected)
colnames(data) <- categories
# Create grouped bar plot
barplot(data, beside = TRUE,
col = c("#f5576c", "#9c27b0"),
legend = c("Observed", "Expected"),
main = "Rat Maze Arm Preferences",
xlab = "Maze Arm",
ylab = "Frequency",
ylim = c(0, 30))
Research Question: Are births equally distributed across days of the week?
Data: Hospital records show the following births:
| Day | Mon | Tue | Wed | Thu | Fri | Sat | Sun |
|---|---|---|---|---|---|---|---|
| Births | 28 | 32 | 29 | 31 | 35 | 18 | 17 |
Total births: 190
Expected per day (if equal): 190 ÷ 7 = 27.14
# Your turn! Complete this R code:
# Step 1: Enter the observed frequencies
births <- c(28, 32, 29, 31, 35, 18, 17)
names(births) <- c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
# Step 2: Run Chi-square test
result <- chisq.test(births)
result
# Step 3: Visualize
barplot(births, col = "#f5576c",
main = "Births by Day of Week",
ylab = "Number of Births")
Chi-squared test for given probabilities
data: births
X-squared = 14.63, df = 6, p-value = 0.023
Interpretation: χ² = 14.63, p = 0.023 < 0.05. We reject H₀. Births are NOT equally distributed across days. Looking at the data, weekends (Sat/Sun) have notably fewer births - likely due to scheduled C-sections and inductions happening on weekdays!
Research Question: Do flower colors follow Mendelian 3:1 ratio?
Background: According to Mendelian genetics, we expect 75% purple flowers and 25% white flowers.
Observed data: 152 purple, 48 white (n = 200 total)
# Test against 3:1 ratio (0.75 and 0.25 proportions)
flowers <- c(152, 48)
names(flowers) <- c("Purple", "White")
# Specify expected proportions
chisq.test(flowers, p = c(0.75, 0.25))
# Calculate expected frequencies manually
expected <- 200 * c(0.75, 0.25)
expected # Should be 150 and 50
Chi-squared test for given probabilities
data: flowers
X-squared = 0.107, df = 1, p-value = 0.744
Interpretation: χ² = 0.107, p = 0.744 >> 0.05. We fail to reject H₀. The observed data (152:48) fits the expected 3:1 Mendelian ratio very well. This supports Mendelian inheritance!
Question 1: You test 100 animals for color preference. Observed: Red=35, Blue=40, Green=25. You expect equal preferences. What are the expected frequencies?
Question 2: You get χ² = 8.5, df = 3, p = 0.037. What do you conclude?
Question 3: A study has 4 categories. What are the degrees of freedom?
Mistake 1: Using raw data instead of frequencies
# WRONG - Don't use individual observations
responses <- c("A", "B", "A", "C", "B", "A")
chisq.test(responses) # Error!
# CORRECT - Use frequency counts
freq <- table(responses) # Converts to frequencies
chisq.test(freq)
Mistake 2: Forgetting that totals must match
Your expected frequencies must sum to the same total as your observed frequencies!
❌ Observed total = 100, Expected total = 120 → ERROR
✅ Observed total = 100, Expected total = 100 → CORRECT
Mistake 3: Misinterpreting non-significant results
If p > 0.05, we DON'T conclude "the distributions are the same." We say "we don't have evidence they differ" - absence of evidence isn't evidence of absence!
Mistake 4: Ignoring the assumption about expected frequencies
Chi-square requires expected frequencies ≥ 5 in all categories. We'll cover this more in Module 4!
Here's how to report Chi-square goodness-of-fit results in APA style:
Study: Rats choosing among three maze arms (n=60)
Results:
"A chi-square goodness-of-fit test was conducted to determine whether rats showed equal preference for three maze arms. The distribution of choices did not significantly differ from equal proportions, χ²(2) = 4.30, p = .117. Rats selected the left arm 15 times (25%), center arm 18 times (30%), and right arm 27 times (45%). Although there was a numerical preference for the right arm, this pattern could be due to chance variation."
Essential elements to include:
Research Question: Do neurons fire at uniform rates across four time periods?
Background: You record neural activity in 4 consecutive time periods and count spikes.
Observed spike counts:
| Time Period | 0-250ms | 250-500ms | 500-750ms | 750-1000ms |
|---|---|---|---|---|
| Spikes | 45 | 38 | 52 | 45 |
Your tasks:
# Complete this analysis:
# Step 1: Enter data
spikes <- c(45, 38, 52, 45)
names(spikes) <- c("0-250ms", "250-500ms", "500-750ms", "750-1000ms")
# Step 2: Calculate totals
total <- sum(spikes)
total # Should be 180
# Step 3: Expected frequency (if uniform)
expected_each <- total / 4
expected_each # Should be 45
# Step 4: Run chi-square
result <- chisq.test(spikes)
result
# Step 5: Visualize
barplot(spikes, col = c("#f093fb", "#f5576c", "#9c27b0", "#e91e63"),
main = "Neural Spike Counts by Time Period",
ylab = "Number of Spikes",
las = 2) # Rotates x-axis labels
abline(h = expected_each, lty = 2, col = "blue", lwd = 2)
legend("topright", legend = "Expected", lty = 2, col = "blue", lwd = 2)
Chi-squared test for given probabilities
data: spikes
X-squared = 2.622, df = 3, p-value = 0.4537
Calculations:
Interpretation: χ²(3) = 2.62, p = .454. We fail to reject H₀. The neural firing rate does not significantly differ from uniform across the four time periods. Although there is some variation (38 to 52 spikes), this could easily occur by chance.
Write-up:
"A chi-square goodness-of-fit test examined whether neural spike counts were uniformly distributed across four consecutive 250ms time periods. The distribution did not significantly differ from uniform, χ²(3) = 2.62, p = .454, suggesting consistent firing rates over time."
Follow these steps every time:
H₀: Distribution matches expected; H₁: Distribution differs from expected
• Categorical variable
• Independent observations
• Expected frequencies ≥ 5
Based on your null hypothesis (equal proportions, specific ratio, etc.)
chisq.test(observed, p = c(...))
Look at χ², df, and p-value. If p < .05, reject H₀
Create bar plot, write up results with all key statistics
Key Takeaways:
chisq.test(observed, p = c(...))Next up: Module 3 covers Chi-square Test of Independence - testing relationships between TWO categorical variables!