Effect Sizes For ANOVAs

Eta2

In the context of ANOVA-like tests, it is common to report ANOVA-like effect sizes. These effect sizes represent the amount of variance explained by each of the model’s terms, where each term can be represented by 1 or more parameters.

For example, in the following case, the parameters for the treatment term represent specific contrasts between the factor’s levels (treatment groups) - the difference between each level and the reference level (obk.long == 'control').

data(obk.long, package = "afex") # modify the data slightly for the demonstration: obk.long <- obk.long[1:240 %% 3 == 0, ] obk.long$id <- seq_len(nrow(obk.long)) m <- lm(value ~ treatment, data = obk.long) parameters::model_parameters(m) > Parameter | Coefficient | SE | 95% CI | t(77) | p > ------------------------------------------------------------------ > (Intercept) | 4.28 | 0.36 | [3.56, 5.00] | 11.85 | < .001 > treatment [A] | 1.97 | 0.54 | [0.89, 3.05] | 3.64 | < .001 > treatment [B] | 2.09 | 0.47 | [1.15, 3.03] | 4.42 | < .001 > > Uncertainty intervals (equal-tailed) and p-values (two-tailed) computed > using a Wald t-distribution approximation.

But we can also ask about the overall effect of treatment - how much of the variation in our dependent variable value can be predicted by (or explained by) the variation between the treatment groups. Such a question can be answered with an ANOVA test:

parameters::model_parameters(anova(m)) > Parameter | Sum_Squares | df | Mean_Square | F | p > ----------------------------------------------------------- > treatment | 72.23 | 2 | 36.11 | 11.08 | < .001 > Residuals | 250.96 | 77 | 3.26 | | > > Anova Table (Type 1 tests)

As we can see, the variance in value (the sums-of-squares, or SS) has been split into pieces:

  • The part associated with treatment.
  • The unexplained part (The Residual-SS).

We can now ask what is the percent of the total variance in value that is associated with treatment. This measure is called Eta-squared (written as \(\eta^2\)):

\[ \eta^2 = \frac{SS_{effect}}{SS_{total}} = \frac{72.23}{72.23 + 250.96} = 0.22 \]

and can be accessed via the eta_squared() function:

library(effectsize) options(es.use_symbols = TRUE) # get nice symbols when printing! (On Windows, requires R >= 4.2.0) eta_squared(m, partial = FALSE) > # Effect Size for ANOVA (Type I) > > Parameter | η² | 95% CI > ------------------------------- > treatment | 0.22 | [0.09, 1.00] > > - One-sided CIs: upper bound fixed at [1.00].

Adding More Terms

When we add more terms to our model, we can ask two different questions about the percent of variance explained by a predictor - how much variance is accounted by the predictor in total, and how much is accounted when controlling for any other predictors. The latter questions is answered by the partial-Eta squared (\(\eta^2_p\)), which is the percent of the partial variance (after accounting for other predictors in the model) associated with a term:

\[ \eta^2_p = \frac{SS_{effect}}{SS_{effect} + SS_{error}} \] which can also be accessed via the eta_squared() function:

m <- lm(value ~ gender + phase + treatment, data = obk.long) eta_squared(m, partial = FALSE) > # Effect Size for ANOVA (Type I) > > Parameter | η² | 95% CI > ----------------------------------- > gender | 0.03 | [0.00, 1.00] > phase | 9.48e-03 | [0.00, 1.00] > treatment | 0.25 | [0.11, 1.00] > > - One-sided CIs: upper bound fixed at [1.00]. eta_squared(m) # partial = TRUE by default > # Effect Size for ANOVA (Type I) > > Parameter | η² (partial) | 95% CI > --------------------------------------- > gender | 0.04 | [0.00, 1.00] > phase | 0.01 | [0.00, 1.00] > treatment | 0.26 | [0.12, 1.00] > > - One-sided CIs: upper bound fixed at [1.00].

(phase is a repeated-measures variable, but for simplicity it is not modeled as such.)

In the calculation above, the SSs were computed sequentially - that is the SS for phase is computed after controlling for gender, and the SS for treatment is computed after controlling for both gender and phase. This method of sequential SS is called also type-I test. If this is what you want, that’s great - however in many fields (and other statistical programs) it is common to use “simultaneous” sums of squares (type-II or type-III tests), where each SS is computed controlling for all other predictors, regardless of order. This can be done with car::Anova(type = ...):

eta_squared(car::Anova(m, type = 2), partial = FALSE) > # Effect Size for ANOVA (Type II) > > Parameter | η² | 95% CI > ----------------------------------- > gender | 0.05 | [0.00, 1.00] > phase | 9.22e-03 | [0.00, 1.00] > treatment | 0.24 | [0.11, 1.00] > > - One-sided CIs: upper bound fixed at [1.00]. eta_squared(car::Anova(m, type = 3)) # partial = TRUE by default > # Effect Size for ANOVA (Type III) > > Parameter | η² (partial) | 95% CI > --------------------------------------- > gender | 0.07 | [0.01, 1.00] > phase | 0.01 | [0.00, 1.00] > treatment | 0.26 | [0.12, 1.00] > > - One-sided CIs: upper bound fixed at [1.00].

\(\eta^2_p\) will always be larger than \(\eta^2\). The idea is to simulate the effect size in a design where only the term of interest was manipulated. This terminology assumes some causal relationship between the predictor and the outcome, which reflects the experimental world from which these analyses and measures hail; However, \(\eta^2_p\) can also simply be seen as a signal-to-noise- ratio, as it only uses the term’s SS and the error-term’s SS.[^in repeated-measure designs the term-specific residual-SS is used for the computation of the effect size].

(Note that in a one-way fixed-effect designs \(\eta^2 = \eta^2_p\).)

Adding Interactions

Type II and type III treat interaction differently. Without going into the weeds here, keep in mind that when using type III SS, it is important to center all of the predictors; for numeric variables this can be done by mean-centering the predictors; for factors this can be done by using orthogonal coding (such as contr.sum for effects-coding) for the dummy variables (and NOT treatment coding, which is the default in R). This unfortunately makes parameter interpretation harder, but only when this is does do the SSs associated with each lower-order term (or lower-order interaction) represent the SS of the main effect (with treatment coding they represent the SS of the simple effects).

# compare m_interaction1 <- lm(value ~ treatment * gender, data = obk.long) # to: m_interaction2 <- lm( value ~ treatment * gender, data = obk.long, contrasts = list( treatment = "contr.sum", gender = "contr.sum" ) ) eta_squared(car::Anova(m_interaction1, type = 3)) > Type 3 ANOVAs only give sensible and informative results when covariates > are mean-centered and factors are coded with orthogonal contrasts (such > as those produced by `contr.sum`, `contr.poly`, or `contr.helmert`, but > *not* by the default `contr.treatment`). > # Effect Size for ANOVA (Type III) > > Parameter | η² (partial) | 95% CI > ---------------------------------------------- > treatment | 0.12 | [0.02, 1.00] > gender | 9.11e-03 | [0.00, 1.00] > treatment:gender | 0.20 | [0.07, 1.00] > > - One-sided CIs: upper bound fixed at [1.00]. eta_squared(car::Anova(m_interaction2, type = 3)) > Type 3 ANOVAs only give sensible and informative results when covariates > are mean-centered and factors are coded with orthogonal contrasts (such > as those produced by `contr.sum`, `contr.poly`, or `contr.helmert`, but > *not* by the default `contr.treatment`). > # Effect Size for ANOVA (Type III) > > Parameter | η² (partial) | 95% CI > ---------------------------------------------- > treatment | 0.27 | [0.13, 1.00] > gender | 0.12 | [0.03, 1.00] > treatment:gender | 0.20 | [0.07, 1.00] > > - One-sided CIs: upper bound fixed at [1.00].

If all of this type-III-effects-coding seems like a hassle, you can use the afex package, which takes care of all of this behind the scenes:

library(afex) > Loading required package: lme4 > Loading required package: Matrix > ************ > Welcome to afex. For support visit: http://afex.singmann.science/ > - Functions for ANOVAs: aov_car(), aov_ez(), and aov_4() > - Methods for calculating p-values with mixed(): 'S', 'KR', 'LRT', and 'PB' > - 'afex_aov' and 'mixed' objects can be passed to emmeans() for follow-up tests > - Get and set global package options with: afex_options() > - Set sum-to-zero contrasts globally: set_sum_contrasts() > - For example analyses see: browseVignettes("afex") > ************ > > Attaching package: 'afex' > The following object is masked _by_ '.GlobalEnv': > > obk.long > The following object is masked from 'package:lme4': > > lmer m_afex <- aov_car(value ~ treatment * gender + Error(id), data = obk.long) > Contrasts set to contr.sum for the following variables: treatment, gender eta_squared(m_afex) > # Effect Size for ANOVA (Type III) > > Parameter | η² (partial) | 95% CI > ---------------------------------------------- > treatment | 0.27 | [0.13, 1.00] > gender | 0.12 | [0.03, 1.00] > treatment:gender | 0.20 | [0.07, 1.00] > > - One-sided CIs: upper bound fixed at [1.00].

Tag » Cohen's F Effect Size Anova