Rr‑statistics.co

ANOVA Output Interpreter

ANOVA tests whether three or more groups have meaningfully different averages, and which terms in your model are doing the work. Paste an aov() or car::Anova() table from R to get a per-term plain-English read, eta-squared effect sizes, and a clear verdict on what is driving the variation.

i New to Type I / II / III ANOVA? Read the 4-min primer

What ANOVA does. Analysis of Variance partitions the total variation in an outcome into chunks attributable to each predictor (and to leftover residual noise). Each row in an ANOVA table reports a Sum of Squares (SS), the degrees of freedom (df) it consumed, the resulting Mean Square (SS / df), an F-ratio against the residual mean square, and a p-value.

Why three Types. When predictors are correlated (an unbalanced design), the SS for one term depends on what other terms are already in the model. Type I (sequential) credits each term with the SS it explains after the previously listed terms. Type II adjusts each main effect for all other main effects but ignores interactions. Type III adjusts every term for every other term, including interactions, and matches the marginal-means hypothesis people usually have in mind.

What to report. Beyond F and p, give an effect size: eta-squared (SS_term / SS_total) for the proportion of total variance the term carries, and partial eta-squared (SS_term / (SS_term + SS_resid)) for the share once you set aside the other terms. Conventional cutoffs are 0.01 (small), 0.06 (medium), 0.14 (large), but interpret in your field's context.

Picking which Type. Balanced design with no missingness: all three Types coincide; report any. Unbalanced data and you care about main effects: Type II. Significant interaction or you want SAS-style marginal tests: Type III with sum-to-zero contrasts. Never quote Type I from a model whose term order is not theoretically motivated.

Parses aov() and car::Anova() tables, eta-squared, plain-English term reads, runs in your browser

Try a real-world example to load.

Awaiting paste…
R code RUNNABLE
R Reproduce in R

        
SS contribution per term VISUAL
Bar height = Sum of Squares per term; residual SS shown in grey.
Paste an ANOVA table to render.
Inference

Read more Anatomy of an ANOVA table
Sum of squares partition: SS_total = sum( (y_i - mean(y))^2 ) SS_term = SS explained by that term SS_resid = leftover residual SS SS_total = sum(SS_term) + SS_resid (Type I, balanced design)
The variance pie. Total variation in y is sliced into chunks, one per term, plus an unexplained residual chunk. The exact slicing rule is what differs across Types: Type I assigns each term whatever is left over after the previous terms; Type II/III use partial sums that adjust for other terms. The residual is always what is left after every term has had its turn.
Mean square and F-ratio: MS_term = SS_term / df_term MS_resid = SS_resid / df_resid F = MS_term / MS_resid under H0 (term has no effect): F ~ F(df_term, df_resid)
From SS to F. Each term's mean square is its SS scaled by its df. Dividing by the residual MS gives an F-ratio: a value near 1 means the term explains no more than noise; large F means the term explains a lot more than its df budget would predict by chance.
Effect sizes: eta^2_j = SS_j / SS_total partial eta^2_j = SS_j / (SS_j + SS_resid) omega^2_j = (SS_j - df_j * MS_resid) / (SS_total + MS_resid)
Why eta-squared. p-values rank terms by improbability under the null but say nothing about how big the effect is. Eta-squared answers "what fraction of total variance does this term carry?", and partial eta-squared answers "of the variance not already explained by other terms, what fraction does this term carry?". Omega-squared is a less biased version that subtracts the expected SS under the null.
Type I vs II vs III when unbalanced: Type I: SS(A), SS(B|A), SS(A:B|A,B) Type II: SS(A|B), SS(B|A), SS(A:B|A,B) Type III: SS(A|B,A:B), SS(B|A,A:B), SS(A:B|A,B)
The Type triad. All three reduce to the same answer when the design is balanced (equal cell counts and no missing combinations). When unbalanced, Type I depends on the order you typed the terms; Type II tests main effects in a model without their interaction; Type III tests every term holding all others fixed (including interactions) and is what most reporting guidelines now recommend.
Model R-squared: R^2 = 1 - SS_resid / SS_total adj R^2 = 1 - (SS_resid / df_resid) / (SS_total / (n - 1))
Whole-model fit. R-squared from an ANOVA table is the same quantity you would read off summary(lm()): one minus the residual share. Adjusted R-squared penalizes the parameter count. Both fall out of the table because the table already partitions the total variance.
Caveats When this is the wrong tool
If you have…
Use instead
A continuous outcome with no factors
Use the lm() output interpreter. ANOVA tables are most informative when at least one predictor is categorical with more than two levels.
A binary or count outcome
Use the glm() output interpreter (logistic / Poisson). The F-test in this tool assumes Gaussian residuals; for non-Gaussian outcomes the deviance-based analog of ANOVA is the right tool.
Repeated measures or clustered data
A repeated-measures ANOVA layout has an Error() stratum. Parsing one stratum at a time works here, but a mixed-effects model is generally a better fit; see the planned mixed-effects builder tool.
Severely unbalanced design with significant interaction
Type III with sum-to-zero contrasts is the right test, but interpret simple effects (emmeans-style) rather than main effects in isolation. The marginal main-effect F is rarely what you want when interaction is real.
Singular or rank-deficient model
Rows with NA F or zero df are a sign the design matrix is rank-deficient. Drop the offending term or refit with a smaller model; this tool reports the symptom but cannot fix it.
Further reading

Numerical notes: parser handles "< 2.2e-16", scientific notation, signif. codes lines, both column orders (aov: Df-SumSq-MeanSq-F-P; car::Anova: SumSq-Df-F-P), and Type III intercept rows. eta-squared is computed as SS_term / SS_total where SS_total is the column sum; partial eta-squared as SS_term / (SS_term + SS_resid). Numbers may differ from R's effectsize::eta_squared by rounding when only the printed table is available.