Bayesian ANOVA

Info sheet · Statistics for Psychology & Neuroscience

Author

Andrew Bell

Published

August 13, 2026

Info sheet 0.2 (draft) · Prerequisites: one-way ANOVA; reading a Bayes factor · Give feedback ↗

Working notes for the author — not shown to students once collapsed; remove before publishing.

  • [ ]

What you’ll get from this sheet

The Bayesian version of a one‑way ANOVA — and how painless it is. By the end you should be able to:

  1. Run a Bayesian ANOVA with anovaBF().
  2. Read the Bayes factor it returns.

anovaBF() compares a model with a group effect against an intercept‑only (grand‑mean) model, returning a Bayes factor. A large BF favours “the factor matters”; a BF near or below 1 favours the null. It answers the question you actually care about — how much should this data change my belief that the factor matters?

Same syntax, better question

The BayesFactor package makes Bayesian analysis remarkably painless — the syntax mirrors the frequentist functions you already know. Where a frequentist aov() hands you an F‑statistic and a p‑value, anovaBF() returns a Bayes factor comparing the model in which the factor matters against an intercept‑only model. If that Bayes factor is large, the data favour the model where (say) decade affects danceability; if it’s near or below 1, the data favour the null. Notice how directly this answers the researcher’s real question — how much should this dataset shift my belief that decade matters? — rather than the convoluted thing NHST answers.

Effect size drives the Bayes factor

Three decades of danceability. Slide how different the decades really are and watch the Bayes factor for “decade matters” grow:

With the decades on top of one another, the Bayes factor sits near 1 — the data don’t favour “decade matters” over the grand‑mean model. Pull the means apart and BF₁₀ climbs through moderate, strong, and beyond, quantifying exactly how much the data support an effect of decade. And unlike a p‑value, when the effect is genuinely absent the Bayes factor can drop below 1, giving you positive evidence for the null — a conclusion aov() could never license.

See it in code

library(BayesFactor)
# decade must be a factor:
bf <- anovaBF(danceability ~ decade, data = decadeDance)
bf              # BF10 for the 'decade' model vs the intercept-only (null) model

# compare against the frequentist version:
summary(aov(danceability ~ decade, data = decadeDance))   # F and p

anovaBF() returns BF₁₀ = 0.3 for a decade effect. How does that differ from a non‑significant aov()?

BF₁₀ = 0.3 means the data are about 3× more likely under the null (no decade effect) than under the model where decade matters — i.e. moderate evidence for the null. A non‑significant aov() (p > .05) only tells you that you failed to reject the null; it can’t distinguish “evidence for no effect” from “not enough data to tell.” The Bayesian result is the more informative: it actively supports the simpler model, rather than merely failing to overturn it.

The interactive uses a quick BIC approximation to the Bayes factor; the real anovaBF() places carefully chosen priors on the effects, so exact values differ (and depend on the prior — report it). Make sure your grouping variable is a factor, as with aov(). And a Bayesian ANOVA is still an omnibus comparison — “decade matters” doesn’t say which decades differ; for that, compare the specific models or run Bayesian follow‑up contrasts.

Where this shows up next

The same BayesFactor machinery extends to regression, where it can rank whole families of models. See Chapter (Bayesian Methods).