How to Perform ANOVA with statsmodels

How to Perform ANOVA with statsmodels
Image by Editor | Canva

Introduction

Analysis of variance (ANOVA) compares the means across two or more groups to test the null hypothesis that all group means are equal. It breaks down the total variance in the data into two components: variance between groups and variance within groups.

There are several types of ANOVA, predominantly including:

  • One-way ANOVA: Tests for differences in means based on one categorical independent variable
  • Two-way ANOVA: Tests the effects of two independent categorical variables and can also assess the interaction effect between them

In Python, the statsmodels library makes ANOVA easy to perform. It supports both one-way and two-way ANOVA. This article demonstrates how to use statsmodels for ANOVA with simple examples. You’ll learn how to prepare data, fit models, and interpret the results.

Before getting started, make sure you have the required libraries installed:

pip install pandas statsmodels matplotlib seaborn

Now, you can import the necessary modules:

import pandas as pd
import statsmodels.api as sm
from statsmodels.formula.api import ols

One-Way ANOVA

Let’s walk through a one-way ANOVA example. Suppose we want to test whether the average test scores differ across three different teaching methods.

Creating Sample Data

We’ll create a small dataset with three groups representing the teaching methods.

data = {
    'score': [88, 75, 90, 85, 60, 78, 70, 65, 72],
    'method': ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C']
}
df = pd.DataFrame(data)

Fitting the One-Way ANOVA Model

Use the formula API from statsmodels to define the model. The C() syntax tells statsmodels to treat method as a categorical variable.

model = ols('score ~ C(method)', data=df).fit()
anova_table = sm.stats.anova_lm(model, typ=2)
print(anova_table)
              sum_sq   df        F    PR(>F)
C(method) 363.555556  2.0  2.21981  0.189845
Residual  491.333333  6.0      NaN       NaN

This table includes the F-statistic and p-value. A p-value less than 0.05 suggests that at least one group mean is different.

Two-Way ANOVA (Interaction Effects)

Two-way ANOVA evaluates how two independent categorical variables affect a continuous dependent variable. It also allows for testing whether the effect of one factor depends on the level of the other—an interaction effect.

Creating Sample Data

Suppose we are testing how teaching method and student gender affect test scores.

data = {
    'score': [88, 75, 90, 85, 60, 78, 70, 65, 72, 80, 67, 92],
    'method': ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C', 'A', 'B', 'C'],
    'gender': ['M', 'F', 'M', 'M', 'F', 'M', 'F', 'F', 'M', 'F', 'M', 'F']
}
df = pd.DataFrame(data)

Fit the Two-Way ANOVA Model (with Interaction)

The formula includes main effects (method, gender) and their interaction term, method:gender:

model = ols('score ~ C(method) + C(gender) + C(method):C(gender)', data=df).fit()
anova_table = sm.stats.anova_lm(model, typ=2)
print(anova_table)
                          sum_sq   df         F    PR(>F)
C(method)             317.458333  2.0  1.609195  0.275733
C(gender)             180.625000  1.0  1.831174  0.224748
C(method):C(gender)   170.041667  2.0  0.861940  0.468756
Residual              591.833333  6.0       NaN       NaN

The ANOVA table shows the main effects of method and gender, along with their interaction (method:gender). A significant interaction means the effect of one variable depends on the level of the other.

Post Hoc Testing

ANOVA tells you whether there are significant differences, but not which specific groups differ. Post hoc tests (like Tukey’s Honest Significant Difference, or HSD) help identify which group means differ significantly from each other.

We will use the data from our one-way ANOVA example to perform Tukey’s HSD (Honest Significant Difference) test.

from statsmodels.stats.multicomp import pairwise_tukeyhsd

# Reload the one-way ANOVA data
data = {
    'score': [88, 75, 90, 85, 60, 78, 70, 65, 72],
    'method': ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C']
}
df = pd.DataFrame(data)

tukey = pairwise_tukeyhsd(endog=df['score'], groups=df['method'], alpha=0.05)
print(tukey)
Multiple Comparison of Means - Tukey HSD, FWER=0.05 
=====================================================
group1 group2 meandiff p-adj   lower    upper  reject
-----------------------------------------------------
  A      B   -10.3333 0.2974 -28.4904  7.8237  False
  A      C   -13.6667 0.1343 -31.8237  4.4904  False
  B      C    -3.3333 0.8427 -21.4904 14.8237  False

In this case, none of the pairwise comparisons are statistically significant (reject = False).

Final Thoughts

ANOVA is a powerful method for comparing group means, helping identify whether differences between groups are statistically meaningful.

The statsmodels library in Python makes it simple to perform both one-way and two-way ANOVA. You can also include interaction effects to see how two variables work together.

Always check p-values to decide if results are significant, and, if they are, follow up with post hoc tests like Tukey’s HSD.

Leave a Reply

Your email address will not be published. Required fields are marked *