Bayesian ANOVA
Info sheet · Statistics for Psychology & Neuroscience
Warning✎ Editing notes — to do / to check
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:
- Run a Bayesian ANOVA with
anovaBF(). - 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
TipCheck your understanding
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).