ANOVA (Analysis of Variance) › Assumptions of ANOVA

Michael BrenndoerferJanuary 5, 20262 min read
Machine Learning from ScratchAll chapters
Part 2 of 9Hypothesis Testing
Chapter 17ANOVA (Analysis of Variance) › Assumptions of ANOVA
Reading section 8 of 13 · Assumptions of ANOVA · 2 minSection 8 of 13 · 2 min

Book contents

Section 8 of 13 · 2 min read

ANOVA (Analysis of Variance) › Assumptions of ANOVAOne section · Sections in this chapter8 / 13 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Like the t-test, ANOVA relies on several assumptions. Understanding these helps you interpret results appropriately and choose alternatives when needed.

1. Independence

Observations must be independent both within and between groups. This is primarily a study design issue:

  • Random sampling from populations
  • Random assignment to treatment groups
  • No clustering or repeated measures (for one-way ANOVA)

2. Normality

Data within each group should be approximately normally distributed. Moderate departures from normality usually have little effect on ANOVA, especially when:

  • Sample sizes are similar across groups
  • Sample sizes are reasonably large (n > 15-20 per group)
  • Distributions are not extremely skewed

For small samples or severely non-normal data, consider the Kruskal-Wallis test (non-parametric alternative).

3. Homogeneity of Variance (Homoscedasticity)

All groups should have similar variances. This assumption is important because the F-test uses a pooled variance estimate.

Checking: Use Levene's test or visual inspection of group spreads.

In[10]:
Code
# Check homogeneity of variance
levene_stat, levene_p = stats.levene(fertilizer_a, fertilizer_b, fertilizer_c)

print("Assumption Check: Homogeneity of Variance")
print("=" * 50)
print(f"Levene's test: W = {levene_stat:.3f}, p = {levene_p:.4f}")
print()
if levene_p > 0.05:
    print("No evidence of unequal variances (p > 0.05)")
    print("Standard ANOVA is appropriate.")
else:
    print("Evidence of unequal variances (p < 0.05)")
    print("Consider Welch's ANOVA or transformation.")
Out[10]:
Console
Assumption Check: Homogeneity of Variance
==================================================
Levene's test: W = 0.471, p = 0.6295

No evidence of unequal variances (p > 0.05)
Standard ANOVA is appropriate.

When Assumptions Are Violated

ViolationAlternative
Non-normalityKruskal-Wallis test
Unequal variancesWelch's ANOVA
BothKruskal-Wallis or permutation test
In[11]:
Code
# Demonstrate alternatives

# Welch's ANOVA (doesn't assume equal variances)
# Note: scipy doesn't have Welch's ANOVA directly, but you can use Alexander-Govern test
# For demonstration, we'll use Kruskal-Wallis

# Kruskal-Wallis test (non-parametric)
kw_stat, kw_p = stats.kruskal(fertilizer_a, fertilizer_b, fertilizer_c)

print("Alternative Tests:")
print("-" * 50)
print(f"Kruskal-Wallis H = {kw_stat:.2f}, p = {kw_p:.4f}")
print()
print("The Kruskal-Wallis test also finds a significant difference,")
print("confirming our ANOVA results.")
Out[11]:
Console
Alternative Tests:
--------------------------------------------------
Kruskal-Wallis H = 22.15, p = 0.0000

The Kruskal-Wallis test also finds a significant difference,
confirming our ANOVA results.