Opens in a new tab

METHOD GUIDE

One-Way ANOVA in R
aov or oneway.test, and Choosing the Post Hoc Test

R offers two routes to the same omnibus question, one that assumes equal variances and feeds the usual follow-up tests and one that does not. The route chosen also decides which pairwise comparisons may follow and which degrees of freedom belong in the report.

IN SHORT

Two Routes to the F Test and What Each One Reports

One-way ANOVA compares the means of a continuous outcome across the levels of a single between-subjects factor, and its omnibus test asks whether at least one population mean differs from the others. To run a one-way ANOVA in R, make the grouping variable a factor, then use the aov function in R when variances are similar or oneway.test() when they are not, since the second does not assume equal variances by default. The follow-up comparisons and the effect size are chosen to match that route. OnlineSPSS, a specialist statistical consultancy for academic, clinical and professional research, carries out and reviews this analysis through an in-house PhD-level statistician.

ANALYSIS SUPPORT

Analysis Support for This Method

The model call is one line in R, while the choices around it, which variance assumption, which comparisons and which adjustment, belong to the design and are settled before the output is read.

One-Way ANOVA

The comparison of three or more independent group means carried out in R or another program, with the variance handling, follow-up tests and reporting agreed for your design.

Explore One-Way ANOVA
Kruskal-Wallis Test

A rank-based comparison of three or more independent groups, for an ordinal outcome or when the distributional assumptions behind a comparison of means are not tenable.

Explore Kruskal-Wallis Test

BEFORE YOU RUN IT

Checks to Make Before aov() or oneway.test()

A one-way model in R is defined by how the grouping variable is stored and by the comparisons planned for it, and both are settled before the first fit.

Independent Groups, One Factor Each participant is in one group and measured once. Repeated measurements or clustered participants need a within-subjects or multilevel model, not a one-way model, whatever the file looks like.

A Real Factor in R If the group codes are numbers, aov() treats the variable as a covariate and fits a straight line with one degree of freedom. Convert it with factor() and check the group degrees of freedom.

Unequal Spread, Unequal n The classic F and Tukey comparisons assume similar variances, and ignoring unequal ones does most harm when group sizes differ. Inspect the spread by group and prefer the route without that assumption when it is doubtful.

Comparisons Named in Advance Name the comparisons and the adjustment before reading p. A planned set of contrasts and an all-pairs exploration answer different questions, and the report labels which one was run.

IN R

How to Run a One-Way ANOVA in R

Base R supplies aov(), oneway.test() and TukeyHSD(). Games-Howell and the effect sizes come from add-on packages, so the reference list carries each package with its release.

  1. Confirm the design: one continuous outcome, one between-subjects factor with three or more levels.
  2. Convert the grouping variable with factor(), then check table() and levels().
  3. Plot the outcome by group, for example with boxplot(), and compare spread, skew and outliers.
  4. Fit fit <- aov(outcome ~ group, data = d) and read summary(fit), or call oneway.test(outcome ~ group, data = d) for the version that does not assume equal variances.
  5. Follow up with TukeyHSD(fit) when variances are similar, or games_howell_test() in rstatix when they are not.
  6. Obtain eta_squared() or omega_squared() from the effectsize package, and save the script.

READING THE OUTPUT

Reading summary(aov), oneway.test and TukeyHSD

The three functions print in different layouts, and the common slip is quoting degrees of freedom from one table beside a statistic from another.

Output element What it tells you What to check
Df row for the factor The number of groups minus 1 That it matches the number of levels, since 1 flags a numeric code
Residuals row Within-group degrees of freedom, sum of squares and mean square That the error df equals N minus the number of groups
F value and Pr(>F) The classic omnibus statistic and its p-value That it is reported only when similar variances are plausible
One-way analysis of means The header of oneway.test, with a note when equal variances are not assumed That the denominator df is quoted as printed, non-integer values included
Tukey multiple comparisons For each pair, diff, lwr, upr and p adj That the sign of diff is read from the level order, later minus earlier
Family-wise confidence level The simultaneous coverage of all pairwise intervals That the 95% level is described as family-wise, not per comparison
Effect size output Eta squared or omega squared with an interval, from an add-on That the alternative argument, which sets a one-sided interval by default in some releases, is checked

REPORTING

Reporting the F Test and the Pairwise Follow-Up

The function that produced the F decides the degrees of freedom to quote and the follow-up that can stand beside it.

Write F(df1, df2) = ___, p = ___, taking the denominator degrees of freedom exactly as printed by whichever function you ran, and say which one it was. Add omega squared or eta squared = ___ with its 95% CI [___, ___], and name the effect size, since aov and oneway.test print none. Give the mean, the standard deviation and the n of each group. For the follow-up, state the method, the adjustment and its family, then report each pair as a mean difference with its adjusted interval rather than as stars. Say whether the comparisons were planned or exploratory, and do not describe a non-significant pair as showing that two means are equal. If the Welch F is reported, say that the effect size was computed from the aov model.

Route NamedDenominator dfEffect Size With CIFollow-Up MethodAdjusted Intervals

COMMON MISTAKES

Coding and Follow-Up Faults in aov() Scripts

The first two arise before the F test is read, in how the outcome is checked and how the groups are coded.

Normality Checked on the Raw Outcome Testing the whole outcome column for normality ignores that the model concerns the residuals within groups. Plots of the residuals from the fitted model are the more relevant check.

Stray Categories Counted A misspelled label or a placeholder code creates an extra group with a handful of cases, which changes the number of groups and the error degrees of freedom. Count the cases per level before fitting.

Route Not Matched Reporting the classic F but following up with Games-Howell, or Welch with Tukey, mixes variance assumptions. The omnibus and the pairwise tests should rest on the same assumption.

Significance Gate Assumed Treating a significant omnibus F as permission to test all pairs, or a non-significant one as a ban, confuses planned contrasts with exploration. State which comparisons were planned.

Stars Instead of Estimates Marking pairs with asterisks hides how large each difference is. Mean differences with adjusted intervals show the size and the uncertainty, and they come from the same output.

Coefficients Read as Post Hoc Tests The coefficients from summary.lm() of a fitted model compare each level with the reference level under R's default treatment contrasts. They cover only some pairs and carry no adjustment, so they cannot replace the follow-up tests.

Pairwise table in your draft? Independent Statistical Review checks the factor coding, the route chosen and the follow-up tests before you submit.

Request an Assessment

FREQUENTLY ASKED QUESTIONS

Questions About the aov and oneway.test Output

Two of the answers trace a surprising number in the R output back to how the model was specified, and one concerns an interval setting that is easy to miss.

The grouping variable was read as a number, so aov() fitted a straight line instead of a one-way model. Convert it with factor() and refit. The factor row then shows the number of groups minus 1, and the residual degrees of freedom adjust accordingly, so the F test answers the question the design asked.

No, TukeyHSD needs a fitted aov object and rests on the pooled-variance model. After a result from oneway.test, use a method designed for unequal variances, such as games_howell_test() in rstatix, or pairwise.t.test() with pool.sd = FALSE and an adjustment. Name the method and the adjustment in the report.

Pass the aov object to eta_squared() or omega_squared() in the effectsize package. Its interval argument has defaulted to a one-sided interval in some releases, so set alternative = “two.sided” when a two-sided 95% interval is what the report states. Name the measure, because eta squared and omega squared differ in value.

Yes. Whether the group variable is a factor, whether the omnibus route and the follow-up rest on the same variance assumption and whether the effect size is named are all checked by an in-house PhD-level statistician, who can also fit the model on your data. Once the model is fixed, presenting the comparisons is the work of Results Reporting & Interpretation. Which group differences matter for your theory is your call.

Your data and project details are handled confidentially, and project information is not published. Researcher names and institutions are not used publicly without permission. An NDA is available where required and can be arranged before sensitive materials are shared. Read more about confidentiality and data security.

You share your research question, design and relevant materials, such as the dataset or the output you have, and a statistically trained Research Coordinator reviews the request and responds the same day. The analysis, deliverables, timeline and one fixed project fee are then confirmed before any work begins, so the timeline follows from the agreed scope.

Still have a question? Find more answers in our full FAQ.

View All FAQs →

NEXT STEP

Which Route and Which
Comparisons Fit Your Groups?

The omnibus route and the pairwise follow-up should rest on the same variance assumption, and an agreed review checks that your call to aov() or oneway.test() and the comparisons after it do.

No Commitment Required

Strictly Confidential

Fixed Project Fee

In-House PhD-Level Statisticians

Same-Day Response

Serving Researchers Since 2014