ANOVA Family · General Linear Model
Bayesian ANOVA
A Bayesian ANOVA weighs the evidence for and against group means differing.
A Bayesian ANOVA takes one continuous outcome from three or more separate groups and weighs how much the data favor different population means over equal ones, or the reverse.
Does it matter which version of a mindfulness app students use, or do all three leave them about equally stressed? Ninety undergraduates were randomly assigned, 30 each, to a guided-audio, written or gamified version of the same app for four weeks, then rated their stress on a 0–40 questionnaire.
- Tests
- Evidence for differences among population means versus none
- Observations
- Independent
- Parametric
- Yes
- Headline Statistic
- BF_{01}
- Effect Size
- Eta Squared
- Groups
- 3+
The Basics
When to Use It
Use it when you have three or more separate groups of different people, one continuous outcome, and you want to weigh the evidence for differences between their averages against the evidence for none. It earns its keep when "no difference" is a real possibility you'd like to be able to support, not just fail to reject. For example:
- Does it matter which version of a mindfulness app students use, or do all three leave them about equally stressed?
- Is working-memory span the same after 10, 20 or 30 minutes of a video game, or does it change with play time?
- Do three wordings of a survey question produce different average trust ratings, or equivalent ones?
Vocabulary You Need
Definition Bayes Factor (BF_{10})
A ratio comparing how well two hypotheses predicted the observed data: each hypothesis's marginal likelihood (how well it predicted the data, averaged over its prior distribution), divided by the other's. For continuous data these are predictive densities (heights of a curve at the observed data), not probabilities of those exact observations. BF₁₀ puts the alternative on top and BF₀₁ = 1 / BF₁₀ puts the null on top, so BF₁₀ = 5 and BF₀₁ = 5 are equally strong, in opposite directions. Values near 1 mean the data can't tell the hypotheses apart. Unlike a p-value, it can show evidence for the null, not just a failure to reject it. It depends on the prior distributions, so report which ones you used. Glossary →
Definition Prior Distribution
A probability distribution that says which values of a parameter, such as the size of an effect, a hypothesis considers plausible before the data are in. In a Bayes factor it's how each hypothesis makes its predictions: a narrow prior bets on small effects, a wide one spreads its bets over large effects too. The Bayes factor depends on it, so the prior is chosen before the analysis, usually a published default, and results are checked with other reasonable priors. Glossary →
Definition Posterior Probability (P(H \mid \text{data}))
The probability of a hypothesis after the data are in. It combines the Bayes factor with the prior odds, how probable the hypotheses seemed beforehand: posterior odds = Bayes factor × prior odds. With equal prior odds and two hypotheses, the null's posterior probability is BF₀₁ / (1 + BF₀₁). Unlike a p-value, it is a probability about the hypothesis, but it's only as sensible as the prior odds behind it. Glossary →
Definition F Statistic (F)
The variance due to an effect divided by the error variance it is tested against: in a between-subjects ANOVA, the between-groups variance over the within-groups variance; in a repeated-measures ANOVA, the conditions' variance over the inconsistency in how people change across them. It is near 1 when there's no real effect and grows as the effect stands out from the error. It is compared with an F distribution, which has two degrees of freedom, to get a p-value. Glossary →
Assumptions and Inference
1. Independent Students (for the Model) Each student's score is independent of everyone else's, within and between groups. Random assignment doesn't ensure this if students share classrooms, teams or other clusters.
- What It Means
- Each person's data comes from a separate, unconnected source, so knowing one person's scores tells you nothing about anyone else's. In designs that measure people more than once, their own scores are meant to be related; it's different people who must be independent. Methods built for clustered data, such as multilevel models and GEE, also allow members of the same group to be related, as long as the analysis names the grouping; then it's the groups that must be independent.
- Applies To
- Observations
- How to Check
- By design, not by a test. Did each person contribute their own data, with no clusters such as roommates, couples, therapy groups or classrooms whose members influence each other? If there are clusters, does the analysis model every one of them?
- How Much It Matters
- A lot. If students used the app together or were recruited in clusters, their scores are more alike than the model expects, and the Bayes factor overstates the evidence in whichever direction it points.
What to Do
- Alternative Test Multilevel Regression (HLM). A multilevel model, Bayesian or classical, which accounts for the clustering.
- Design Change Assign and measure each person separately, or analyze cluster averages.
2. Normality Within Groups (for the Model) The default Bayesian ANOVA models each group's scores as normal around its mean. It doesn't become distribution-free because it uses Bayes factors: the Bayes factor compares how well the specified models predicted the data, so a poor likelihood changes the evidence itself. Larger samples make estimates more stable, but they don't make a misspecified model irrelevant.
- What It Means
- The test's model assumes the scores it relies on are roughly normal: the scores within each group (or the scores themselves, for a one-sample test), the difference scores in a paired design, or the residuals (the errors left around a model's predictions) in a regression. For p-values and confidence intervals, what really matters is that the estimates (such as a mean, a difference between means or a model's coefficients) are roughly normal across repeated samples. A large enough sample usually provides that; how large depends on how skewed the scores are and how extreme their outliers.
- Applies To
- Residuals
- How to Check
- Here a residual is each student's score minus their group's average. Plot those in a histogram or Q–Q plot, not the raw scores pooled across groups, which mix three different centers. Look for strong skew, heavy tails or extreme scores. Don't rely on a normality test: with small samples it misses real problems, and with large ones it flags trivial ones.
- How Much It Matters
- The Bayes factor uses the same normal model as the F-test, so outliers pull the group means and inflate the within-groups variance here too, and the evidence shifts with them. With 30 per group and no extreme scores, as in our data, moderate skew is a smaller worry than a few wild scores; check whether one or two of them drive the result. Here the residuals' skewness runs from −0.17 to 0.88 (the text group leans right), and no score is more than 2.5 SDs from its group's mean.
What to Do
-
Alternative Test
Kruskal-Wallis Test. A classical rank-based comparison, for ordered ratings or a question about which groups tend to score higher. It doesn't test equal means, gives no Bayes factor and can't give evidence for no difference. If means are still the question and scores are skewed or heavy-tailed, fit a robust Bayesian model instead, such as one with t-distributed errors (in R,
brmswithfamily = student()). - Transformation Log-transform right-skewed outcomes such as reaction times. Results are then on the log scale.
- Proceed with Caveat Rerun the analysis without the extreme scores and report both Bayes factors if they differ.
3. Equal Variances (for the Model) The default Bayesian ANOVA assumes the groups share one population variance. Equal group sizes help with moderate differences, but substantial differences in spread call for a Bayesian model that gives each group its own variance.
- What It Means
- The outcome varies about as much within each group's population. Tests that pool the groups' variances into one estimate, like Student's t-test and the classic ANOVA, rely on it.
- Applies To
- Variances
- How to Check
- Compare the groups' standard deviations and look at side-by-side box plots. Don't use Levene's test as a gatekeeper: it misses real differences in small samples and flags trivial ones in large samples.
- How Much It Matters
- Matters most when groups differ in both size and spread; with equal groups, like our 30 per version with SDs from 6.00 to 7.00 (Levene's F(2, 87) = 0.94, p = .40), it matters less. The default Bayesian ANOVA estimates one shared variance for all the groups, just as the classical F-test does.
What to Do
- Design Change Keep the groups the same size, which makes a pooled variance far less risky.
-
Alternative Test
Fit a model that gives each group its own SD (in R,
brmswithbf(stress ~ app_version, sigma ~ app_version)) and read the posteriors for the differences. A Bayes factor from such a model needs its own priors and method, so its number isn't comparable with the default one. - Proceed with Caveat Run Welch's ANOVA alongside. It can flag a difference the pooled model hides, but a non-significant Welch p doesn't back up the Bayes factor's evidence for equal means.
Limitations
This Is Not Your Test If…
- You only need a yes/no significance test One-Way Between-Subjects ANOVA →
- You have only two groups (this analysis gives the same Bayes factor) Bayesian Independent-Samples t-Test →
- You measured the same people in every condition (the Bayesian version adds participant as a random factor; see the classical page for the design) One-Way Repeated-Measures ANOVA →
- You have two or more grouping variables Factorial Between-Subjects ANOVA →
- Your outcome is ordered ratings, or your question is which groups tend to score higher rather than whether the means are equal (a classical test, with no Bayes factor) Kruskal-Wallis Test →
- Your outcome isn't continuous (yes/no, categories) Categorical Data and Proportions →
What It Doesn't Tell You
- That the versions are identical. A BF₀₁ of 5.74 says equal means predicted the data better than the default alternative did. Tiny differences, too small for 90 students to detect, are still possible.
- Anything prior-free. The evidence depends on the prior. With wider priors the same data favor equal means more strongly (BF₀₁ = 9.55 at r = 0.707, 16.98 at r = 1; see the prior-sensitivity table in How It's Reported); a prior concentrated on very small effects would favor them less.
- Whether the app works at all. All three groups used an app. With no untreated comparison group, the study says nothing about whether any version lowers stress.
- Who else. The result describes students like these 90, over four weeks, and only as well as a self-report questionnaire measures stress.
Common Mistakes
-
Don'tRead a non-significant p as evidence that the groups are the same.
InsteadReport a Bayes factor, which can show evidence for no difference, or show that the data can't tell.
-
Don'tCall a Bayes factor of 2 or 0.5 evidence for anything.
InsteadCall it inconclusive. Between 1/3 and 3, the data barely favor either hypothesis.
-
Don'tReport a Bayes factor without its prior.
InsteadName the prior and its scale (for example, a Cauchy prior with r = 0.5), and show how the result changes with a wider one.
-
Don'tChoose the prior scale after seeing which one gives the result you want.
InsteadFix it before the analysis, usually the default, and report a robustness check with other scales.
-
Don'tRead a Bayes factor as the probability that a hypothesis is true.
InsteadRead it as how many times better one hypothesis predicted the data than the other. Turning it into a probability needs prior odds too.
Result Decoder
Evidence and Effect Size Guidelines
Benchmarks Strength of Evidence (Bayes Factor)
-
BF₁₀ < 1/100
Extreme for H₀
Extreme evidence for the null hypothesis.
-
1/100 ≤ BF₁₀ < 1/30
Very Strong for H₀
Very strong evidence for the null hypothesis.
-
1/30 ≤ BF₁₀ < 1/10
Strong for H₀
Strong evidence for the null hypothesis.
-
1/10 ≤ BF₁₀ < 1/3
Moderate for H₀
Moderate evidence for the null hypothesis.
-
1/3 ≤ BF₁₀ < 1
Anecdotal for H₀
Barely worth mentioning. Treat it as inconclusive.
-
1 ≤ BF₁₀ < 3
Anecdotal for H₁
Barely worth mentioning. Treat it as inconclusive.
-
3 ≤ BF₁₀ < 10
Moderate for H₁
Moderate evidence for the alternative hypothesis.
-
10 ≤ BF₁₀ < 30
Strong for H₁
Strong evidence for the alternative hypothesis.
-
30 ≤ BF₁₀ < 100
Very Strong for H₁
Very strong evidence for the alternative hypothesis.
-
BF₁₀ ≥ 100
Extreme for H₁
Extreme evidence for the alternative hypothesis.
Labels from Lee and Wagenmakers, adjusted from Jeffreys (1961). They are a rough heuristic, not cutoffs; Kass and Raftery (1995) proposed coarser ones. For BF₀₁, flip the scale: BF₀₁ = 5 is BF₁₀ = 1/5.
Benchmarks Effect Size (Eta Squared)
-
η² < .01
Below Small
Smaller than the conventional small benchmark. Whether an effect this size matters depends on the setting.
-
.01 ≤ η² < .06
Small
A sliver of the variation lines up with the groups. Hard to see without measuring it.
-
.06 ≤ η² < .14
Medium
A noticeable share of the variation lines up with the groups.
-
η² ≥ .14
Large
A large share of the variation lines up with the groups.
Benchmarks are conventions (Cohen, 1988), developed for simple comparisons between groups. They are not measures of practical importance.
How It's Reported
Equation Form
BF01 = 5.74 (JZS prior, r = 0.5), F(2, 87) = 0.71, p = .496, η² = .02, 95% CI [.00, .09]
Table 1. Prior Sensitivity of the Bayes Factor for App Version
| BF_{10} | BF_{01} | P(H_0 \mid \text{data}) | |
|---|---|---|---|
| Medium, r = 1/2 | 0.17 | 5.74 | .85 |
| Wide, r = \sqrt{2}/2 | 0.10 | 9.55 | .91 |
| Ultrawide, r = 1 | 0.06 | 16.98 | .94 |
Note. r is the scale of the Cauchy prior on the standardized effects; the names are R's BayesFactor presets, and “medium” is the default reported above. Posterior probabilities assume even prior odds. Wider priors spread the alternative's bets over larger effects, so these small differences fit it worse and the evidence for equal means grows. It favors equal means at every scale.
Full Text (APA Style)
Stress after four weeks was similar across the three versions of the app: audio (M = 17.00, SD = 6.00), text (M = 18.00, SD = 6.50) and gamified (M = 16.00, SD = 7.00). App version accounted for under 2% of the variation in stress, η² = .02, 95% CI [.00, .09] (a classical confidence interval). A Bayesian one-way ANOVA with the default prior (Cauchy, r = 0.5; Rouder et al., 2012) favored equal means: the data were about 5.74 times better predicted by equal population mean stress scores than by the alternative model, BF01 = 5.74, moderate evidence for the null hypothesis. With wider priors (r = 0.707 and 1), BF01 rose to 9.55 and 16.98. A classical one-way ANOVA was not significant, F(2, 87) = 0.71, p = .496.
- Name the prior and its scale, and the software, so readers can reproduce the Bayes factor.
- Say which way the Bayes factor points: BF₀₁ for evidence for the null, BF₁₀ for evidence for a difference. Give the evidence label too, as a rough guide.
- Report a robustness check with at least one wider prior; conclusions that flip with the prior deserve a caveat.
- Give every group's M and SD, and the effect size with its CI, so readers can see how small the differences are, not just that the evidence favors none.
- If you give the posterior probability of the null, say which prior odds it assumes (.85 here assumes 50–50).
Reading Each Piece
The equation form above, piece by piece, in this order: how big, then how surprising.
| η² = .02 | App version accounts for under 2% of the variation in stress scores in this sample. With F below 1, that's mostly noise: the 95% CI runs from 0 to .09, so don't read it as a small effect. On its own, a sample η² can't tell you whether the true effect is small or zero. Benchmarks ↑ |
| F(2, 87) = 0.71 | The three averages vary less than we'd expect from how much students vary within a version: 0.71 times as much. The 2 and 87 are the degrees of freedom: k − 1 and N − k. |
| BF01 = 5.74 | Equal population mean stress across the three versions predicted the data 5.74 times better than averages differing by the amounts the default prior expects. That's moderate evidence for the null by the conventional labels, which are rough guides, not cutoffs. It's about the data, not yet about how likely the null is. Benchmarks ↑ |
| P(H0 | data) = .85 | Starting from 50–50, there's now about an 85% chance that the population mean stress scores are exactly equal, and a 15% chance they differ. That isn't an 85% chance the versions are practically equivalent, which would need a margin set in advance. A skeptic who started at 20% for the null would end near 59%, so say which prior odds you used. |
| p = .496 | Not significant. But the same p could come from versions that truly work alike or from a study too small to tell them apart; p can't distinguish the two. |
Calculations
The Running Example
The mindfulness-app study: 90 undergraduates, 30 per app version (audio, text, gamified), each with one stress score from 0 to 40.
- Null Hypothesis:
- \mu_{\text{audio}} = \mu_{\text{text}} = \mu_{\text{game}}
- Alternative:
- \text{not all three } \mu \text{ are equal}
Each \mu (“mu”) is the population mean stress score for students using that version, which our group averages of 17, 18 and 16 estimate. Unlike a classical test, the alternative has to say how big the differences might be: its prior distribution on the standardized differences is a Cauchy with scale r = 0.5, the default in R's BayesFactor package. A standardized effect is a rescaled version of a group's distance from the overall mean, in standard deviations (with two groups, r = 0.5 here is the same prior as r = 0.707 on the standardized difference δ in a Bayesian t-test). The Cauchy is a bell-shaped curve with heavier tails: with r = 0.5, the alternative expects half of those effects to lie within ±0.5 SD but leaves room for much larger ones. This default is called the JZS (Jeffreys–Zellner–Siow) prior.
What Your Data Should Look Like
One row per person, with one column naming their group and one numeric column for their score. Each person appears once, in exactly one group. It's the same layout as a classical one-way ANOVA; the difference is in the analysis, not the data.
| participant | app_version | stress |
|---|---|---|
| 1 | game | 12 |
| 2 | text | 21 |
| 3 | game | 19 |
| 4 | text | 34 |
| 5 | text | 25 |
| 6 | text | 23 |
| … 84 more rows | ||
| n | M | SD | |
|---|---|---|---|
| Audio | 30 | 17.00 | 6.00 |
| Text | 30 | 18.00 | 6.50 |
| Gamified | 30 | 16.00 | 7.00 |
| All | 90 | 17.00 | 6.49 |
Simulated data.
Napkin Math
The whole test, one idea at a time. Under each heading, a line says why the step matters, and the green note reads the equation in plain English with the mindfulness-app study's numbers. Collapse all to read just the headings: they tell the whole story on their own.
-
1. Find Each Version's Average and the Overall Average
Everything starts with the group averages, and the easiest way to compare them is to measure each against the average of everyone.
\bar{x}_{\text{grand}} = \dfrac{\sum x_i}{N} =\dfrac{1530}{90}= 17.00 points
\bar{x}_{\text{audio}} = 17.00 points
\bar{x}_{\text{text}} = 18.00 points
\bar{x}_{\text{game}} = 16.00 points
\sum x_i is all 90 stress scores added up, 1530, and N is our 90 students. 1530 ÷ 90 = 17.00 points. The three versions averaged 17 (audio), 18 (text) and 16 (gamified).
-
2. Split the Variation into Differences between Versions and Differences within Them
Some of the spread in stress lines up with which version a student used; the rest is students differing from others on the same version. Both are sums of squared distances.
SS_{\text{between}} = \sum n_j (\bar{x}_j - \bar{x}_{\text{grand}})^2 =30(17 - 17)^2 + 30(18 - 17)^2 + 30(16 - 17)^2= 60
SS_{\text{within}} = 3690
n_j is the 30 students per version and \bar{x}_j each version's average. Text sits 1 above 17 and gamified 1 below, so 0 + 30 + 30 = 60. Within the versions, the squared distances from each group's own average add up to 3690, far more.
-
3. Compare the Spread between Versions with the Spread within Them
Turn each sum into an average by dividing by its degrees of freedom, then take the ratio. If the versions don't matter, it should hover around 1.
F = \dfrac{MS_{\text{between}}}{MS_{\text{within}}} =\dfrac{60 / 2}{3690 / 87} = \dfrac{30}{42.41}= 0.71
MS_{\text{between}} is 60 over k - 1 = 2, which is 30. MS_{\text{within}} is 3690 over N - k = 87, which is 42.41. 30 ÷ 42.41 = 0.71, less than the 1 we'd expect from noise alone.
-
4. Measure How Much of the Variation the Versions Explain
F grows with sample size; η² doesn't. It's the share of all the variation in stress that lines up with the app version, and the Bayes factor formula uses it too.
\eta^2 = \dfrac{SS_{\text{between}}}{SS_{\text{between}} + SS_{\text{within}}} =\dfrac{60}{60 + 3690}= .02
95\%\ \text{CI} = [.00, .09]
SS_{\text{between}} is our 60 and the total is 60 + 3690 = 3750. 60 ÷ 3750 = .016, so the version accounts for 1.6% of the differences in stress.
-
5. See What the Classical Test Can and Can't Say
The classical ANOVA asks how often chance alone would spread three averages at least this far apart if the versions worked equally well and the model's assumptions held. A large p says the data aren't surprising under the null; it can't say whether they support it.
p = P(F_{df_1,\,df_2} \ge F) =P(F_{2,\,87} \ge 0.71)= .496
F_{2,\,87} is an F distribution with 2 and 87 df. The chance it lands at or above 0.71 is .496, about 1 in 2.
-
6. Get a Rough Bayes Factor by Hand
The Bayesian Information Criterion (BIC) scores each model for fit, with a penalty for every extra parameter. Lower is better, so a positive \Delta BIC_{10} means the equal-means model wins. Half the difference between the two scores, exponentiated (exp undoes the natural log, ln), approximates the Bayes factor (Wagenmakers, 2007). It's a quick large-sample approximation, not the Bayes factor under another prior. It doesn't use the JZS prior at all, so it can differ a lot from the default analysis. Report the prior-based Bayes factor and treat the BIC value as a rough check.
BF_{01} \approx \exp\!\left(\dfrac{\Delta BIC_{10}}{2}\right), \quad \Delta BIC_{10} = N \ln\!\dfrac{SS_{\text{within}}}{SS_{\text{total}}} + (k - 1)\ln N =\exp\!\left(\dfrac{90\ln\frac{3690}{3750} + 2\ln 90}{2}\right) = \exp\!\left(\dfrac{-1.45 + 9.00}{2}\right)\Delta BIC_{10} = 7.55
BF_{01} = 43.55
N is our 90 students and k - 1 = 2 is the extra means the difference model estimates. Its better fit lowers its score by 1.45; its two extra parameters add 2 × ln 90 = 9.00. The net 7.55, halved and exponentiated, is about 43.6 in favor of equal means. That is an approximation, far from the 5.74 the default prior gives below.
-
7. Weigh the Evidence with the Default Prior
The default Bayes factor asks how well each hypothesis predicted the data: equal means, or differences with a Cauchy prior of scale 0.5 on their standardized size. There's no closed-form answer: the formula has to be averaged over the prior numerically, which software does. The value below is that software result, which we reproduced with our own integration.
BF_{10} = \int_0^\infty (1 + gn)^{-\frac{k - 1}{2}} \left(1 - \dfrac{gn}{1 + gn}\,\eta^2\right)^{-\frac{N - 1}{2}} \pi(g)\, dg =\int_0^\infty (1 + 30g)^{-1} \left(1 - \dfrac{30g}{1 + 30g}\,(.016)\right)^{-44.5} \pi(g)\, dgBF_{10} = 0.17
n is our 30 students per version, k - 1 = 2 halves to the exponent 1, \eta^2 is our .016, and (N - 1)/2 = 44.5. Averaged over the prior \pi(g) with r = 0.5, the difference model predicted the data 0.17 times as well as equal means did.
-
8. Turn It Around to Read as Evidence for Equal Means
A Bayes factor below 1 is easier to read upside down. BF₀₁ puts the null on top.
BF_{01} = \dfrac{1}{BF_{10}} =\dfrac{1}{0.1741}= 5.74
BF_{10} is our 0.1741. 1 ÷ 0.1741 = 5.74, so equal population means predicted the data 5.74 times better than means differing by the amounts the default prior expects.
-
9. Turn the Evidence into How Probable Equal Means Are
If, before the study, equal and unequal means seemed equally likely, the Bayes factor converts straight into a probability.
P(H_0 \mid \text{data}) = \dfrac{BF_{01}}{1 + BF_{01}} =\dfrac{5.74}{1 + 5.74}= .85
BF_{01} is our 5.74, and with even prior odds the posterior odds are the same 5.74 to 1. 5.74 ÷ 6.74 = .85.
Run It in Software
The code below reads the running example's data from data.csv; save it in the same folder you run the code from.
SPSS (version 30, as documented by IBM)
- Analyze → Bayesian Statistics → One-way ANOVA. SPSS needs a numeric factor, so first recode
app_versioninto a numeric variable (Transform → Recode into Different Variables) with 1 = audio, 2 = text, 3 = game. - Move
stressinto Dependent and the recoded version variable into Factor. - Under Bayesian Analysis, choose Use Both Methods (Bayes factor and posterior distribution).
- Click Bayes Factor and check the method. SPSS's default, labeled JZS, is the Zellner–Siow approach, which scales the prior differently from the Rouder et al. (2012) ANOVA prior that R's BayesFactor and JASP use.
- Click OK.
Reading the Output
Read the group means first, then the Bayes factor, then the classical F and p SPSS prints alongside it.
Because SPSS's default prior isn't the one this page uses, its Bayes factor for these data won't be exactly 5.74 (or its reciprocal, 0.17). Check which way SPSS puts the ratio: the direction is labeled in its output. SPSS also offers Rouder's method in the Bayes Factor dialog, with an inverse-gamma scale parameter b₀ (default 1). That default doesn't correspond to BayesFactor's r = 0.5, so report the method and setting you used. We couldn't run SPSS for this page, so no output is shown; for a result that matches this page exactly, use JASP or R.
Output laid out from this page's computed results, not captured from a live run; labels and layout may differ slightly in your version.
R
library(BayesFactor)
study <- read.csv("data.csv")
study$app_version <- factor(study$app_version, levels = c("audio", "text", "game"))
bf <- anovaBF(stress ~ app_version, data = study) # rscaleFixed = "medium" (r = 0.5) by default
bf # BF10 for app_version against the intercept-only model
1 / extractBF(bf)$bf # BF01
# Robustness: wider priors
anovaBF(stress ~ app_version, data = study, rscaleFixed = "wide") # r = sqrt(2)/2
anovaBF(stress ~ app_version, data = study, rscaleFixed = "ultrawide") # r = 1
# The classical ANOVA, for comparison
summary(aov(stress ~ app_version, data = study))
Bayes factor analysis
--------------
[1] app_version : 0.1741037 ±0.01%
Against denominator:
Intercept only
---
Bayes factor type: BFlinearModel, JZS
[1] 5.743705
Bayes factor analysis
--------------
[1] app_version : 0.1046855 ±0.01%
Against denominator:
Intercept only
---
Bayes factor type: BFlinearModel, JZS
Bayes factor analysis
--------------
[1] app_version : 0.05887926 ±0.01%
Against denominator:
Intercept only
---
Bayes factor type: BFlinearModel, JZS
Df Sum Sq Mean Sq F value Pr(>F)
app_version 2 60 30.00 0.707 0.496
Residuals 87 3690 42.41
The first block is BF₁₀ = 0.174 for app_version against the intercept-only model, and the line after it is BF₀₁ = 1 / 0.174 = 5.74. The wider priors give BF₁₀ = 0.105 (BF₀₁ = 9.55) and 0.059 (BF₀₁ = 16.98). The ± percentage is the numerical error of the integral, negligible here. The classical ANOVA gives F(2, 87) = 0.707, p = .496. app_version must be stored as a factor, or anovaBF will treat it as a number.
Output from a real run: R 4.6.1 (BayesFactor 0.9.12-4.8), run 2026-09-29.
Python
import numpy as np
import pandas as pd
import pingouin as pg
from scipy import integrate
study = pd.read_csv("data.csv")
# Classical ANOVA table, with eta squared (np2)
aov = pg.anova(data=study, dv="stress", between="app_version", detailed=True)
print(aov.round(4))
# Default JZS Bayes factor for a balanced one-way design (Rouder et al., 2012, Eq. 12)
def bf10_anova(eta2, N, k, r=0.5):
n = N / k
def f(g):
prior = r / np.sqrt(2 * np.pi) * g**-1.5 * np.exp(-r**2 / (2 * g))
return (1 + g * n)**(-(k - 1) / 2) * (1 - eta2 * g * n / (1 + g * n))**(-(N - 1) / 2) * prior
return integrate.quad(f, 0, np.inf)[0]
eta2 = aov.loc[0, "np2"]
bf10 = bf10_anova(eta2, N=len(study), k=3)
print(bf10, 1 / bf10)
Source SS DF MS F p-unc np2
0 app_version 60.0 2 30.0000 0.7073 0.4958 0.016
1 Within 3690.0 87 42.4138 NaN NaN NaN
0.1741036518298427 5.7437049107811555
pingouin has a Bayes factor for t-tests (pingouin.bayesfactor_ttest) but not for ANOVA, so the function above does the integral directly. It only works for equal group sizes; for unequal groups or more complex designs, use R's BayesFactor or JASP. The last line is BF₁₀ = 0.174 and BF₀₁ = 5.74. In a one-way design pingouin's np2 (partial η²) equals η².
Output from a real run: Python 3.9.6 (pingouin 0.5.5, scipy 1.13.1, pandas 2.3.3), run 2026-09-29.
JASP
- Open
data.csv. Check thatapp_versionis marked nominal andstresscontinuous (scale). - Open the ANOVA menu and choose ANOVA under the Bayesian heading.
- Move
stressinto Dependent Variable andapp_versioninto Fixed Factors. - Under Additional Options, check that "r scale fixed effects" is 0.5, the default. Change it to 0.707 or 1 for the robustness check.
- Optionally, under Order, choose Compare to null model, and under Bayes Factor choose BF₀₁ to print the evidence for equal means directly.
Reading the Output
The main output is the Model Comparison table, one row per model: the Null model (equal means) and the model with app_version. Read it column by column:
- P(M): each model's prior probability, .50 each by default.
- P(M|data): its probability after seeing the data. Here that should be about .85 for the null and .15 for
app_version, the same as Napkin Math's posterior. - BFM: how much the data changed that model's odds against all the others: about 5.74 for the null and 0.17 for
app_version. - BF₁₀: each model against the one at the top of the table, which is the best model by default. With the null on top,
app_version's BF₁₀ is about 0.17, so BF₀₁ = 5.74. - error %: the numerical error of the integral; small values can be ignored.
JASP's Bayesian ANOVA is built on R's BayesFactor (van den Bergh et al., 2020) with the same default prior, so it should give the R values above. We couldn't run JASP for this page, so no output is shown.
Output laid out from this page's computed results, not captured from a live run; labels and layout may differ slightly in your version.
Impact
Effect Size
Eta squared (η²) expresses the differences as the share of all the variation in the outcome that lines up with the groups, so it has no units and can be compared across studies that used different scales. It still depends on the design: which groups were chosen, how varied the people are, and how reliably the outcome was measured. It's the same number a classical ANOVA gives, and the Bayes factor is built from it.
Of all the differences in students' stress scores, 1.6% line up with which version of the app they used. The other 98% is everything else: exam season, sleep, personality, luck.
The effect size and the Bayes factor answer different questions. η² says how big the differences in this sample are; the Bayes factor says how strongly the data favor some difference over none. A small η² in a small study is weak evidence either way, while here, with 30 per group, the evidence moderately favors none. For a Bayesian estimate of the differences themselves, JASP also summarizes the posterior for each group with a 95% credible interval (van den Bergh et al., 2020). Put together: the observed differences are small, and under the specified prior the data favor exactly equal population means over the alternative; neither result establishes that all differences are too small to matter in practice.
Benchmarks are conventions. Whether a 2-point gap between the most and least stressful versions matters on a 0–40 scale is a question about stress, not statistics.
Benchmarks Eta Squared at a Glance
Strength of Evidence
A Bayesian ANOVA doesn't test for significance. It replaces p with the Bayes factor: how many times better one hypothesis predicted the data than the other. BF₁₀ above 1 favors differences, BF₀₁ above 1 favors equal means, and values near 1 mean the data can't tell.
BF₀₁ = 5.74: the stress scores were about 5.74 times better predicted by the model with equal population mean stress than by the alternative, where the means differ by the amounts the default prior expects. The classical ANOVA on the same data gave p = .496, which only says the result isn't surprising under the null.
That's the difference that matters. A large p means "not enough evidence against the null," whether the null is true or the study was too small. A Bayes factor separates the two: it can show evidence for no difference (BF₀₁ well above 1) or show that the data are inconclusive (BF near 1) (van den Bergh et al., 2020). That evidence is relative: it says equal means predicted the data better than this particular alternative with its prior, not that the means are equal outright. A different alternative can give a different answer, which is what the prior-sensitivity table shows. The evidence labels in the guidelines above, such as "moderate" for a Bayes factor between 3 and 10, are rough conventions (Schönbrodt & Wagenmakers, 2018; Kass & Raftery, 1995, drew coarser bands), not thresholds like α = .05. Read BF₀₁ on the same scale as BF₁₀, flipped.
A Bayes factor is not the probability that a hypothesis is true. Posterior odds are the Bayes factor times the prior odds; only with even prior odds does BF₀₁ = 5.74 become an 85% chance that the population means are exactly equal. That's not the same as the app versions being practically equivalent: that claim needs a margin set in advance (say, differences under 2 stress points) and an analysis of that margin, such as the posterior probability that every difference falls inside it.
Benchmarks Bayes Factor at a Glance
How many times better one hypothesis predicted the data than the other.
Power and Sample Size
Power is the chance that a study detects an effect that's really there. Bayes factors don't have power in that sense, because there's no significance cutoff. Their version is a Bayes factor design analysis: before collecting data, work out how often a planned study would reach convincing evidence, say a Bayes factor of 3 or more, in the right direction, both when the groups truly differ and when they truly don't (Schönbrodt & Wagenmakers, 2018).
With 30 students per version, if the three versions truly worked the same, the study would reach BF₀₁ > 3 about 78% of the time. If the versions truly differed by a medium amount (Cohen's f = 0.25, where f is the standard deviation of the true group means in within-group standard deviations; Cohen, 1992), it would reach BF₁₀ > 3 only about 36% of the time, and about 19% of the time it would point the wrong way, with BF₀₁ > 3. To get BF₁₀ > 3 above 80% of the time, plan for 77 students per version.
Those figures are exact rather than simulated. For a one-way design with equal groups, the default Bayes factor depends on the data only through how much of the variation the groups explain (Rouder et al., 2012), and so only through F. Each chance is then the probability that F lands beyond the point where the Bayes factor crosses 3: under the ordinary F distribution if there's no effect, and under a shifted (noncentral) F distribution, as in a classical power analysis, if there is. For more complex designs, design analysis uses simulation.
Aim for a design that gives compelling evidence whichever hypothesis is true, and plan it before collecting data. The calculator shows both chances; the dashed line is the no-effect case. Try it:
Other Info
Follow-Up and Post Hoc Tests
Post Hoc Tests
- Bayesian Pairwise Comparisons: Use when the overall Bayes factor favors differences, to see which pairs of groups differ. Here it favors equal means, so there is nothing to follow up; comparing pairs anyway would mostly show how weak each difference is.
References
-
Rouder, J. N., Morey, R. D., Speckman, P. L., & Province, J. M. (2012). Default Bayes factors for ANOVA designs. Journal of Mathematical Psychology, 56(5), 356–374.
https://doi.org/10.1016/j.jmp.2012.08.001
“These tests are based on multivariate generalizations of Cauchy priors on standardized effects” (Abstract)
“where R2 is the unadjusted proportion of variance accounted for by the model” (p. 363, Eq. 12)
-
Wagenmakers, E.-J. (2007). A practical solution to the pervasive problems of p values. Psychonomic Bulletin & Review, 14(5), 779–804.
https://doi.org/10.3758/BF03194105
“Because ANOVA is a special case of regression, the same equation also holds for ANOVA.” (p. 798)
- Morey, R. D., & Rouder, J. N. (2026). BayesFactor: Computation of Bayes factors for common designs (R package version 0.9.12-4.8). https://doi.org/10.32614/CRAN.package.BayesFactor
-
van den Bergh, D., van Doorn, J., Marsman, M., Draws, T., van Kesteren, E.-J., Derks, K., Dablander, F., Gronau, Q. F., Kucharský, Š., Komarlu Narendra Gupta, A. R., Sarafoglou, A., Voelkel, J. G., Stefan, A., Ly, A., Hinne, M., Matzke, D., & Wagenmakers, E.-J. (2020). A tutorial on conducting and interpreting a Bayesian ANOVA in JASP. L'Année psychologique, 120(1), 73–96.
https://doi.org/10.3917/anpsy1.201.0073
“the current implementation of Bayesian ANOVA in JASP is based on the R package BayesFactor (Morey & Rouder, 2015) which is itself based on the statistical work by Rouder et al. (2012)” (pp. 81–82)
“For a Bayesian ANOVA, the main component is the Bayesian t-test.” (p. 89)
-
Schönbrodt, F. D., & Wagenmakers, E.-J. (2018). Bayes factor design analysis: Planning for compelling evidence. Psychonomic Bulletin & Review, 25(1), 128–142.
https://doi.org/10.3758/s13423-017-1230-y
“Here we explore Bayes Factor Design Analysis (BFDA) as a useful tool to design studies for maximum efficiency and informativeness.” (Abstract)
“The evidential categories serve as a rough heuristic whose main goal is to prevent researchers from overinterpreting the evidence in the data.” (Table 1 and the paragraph before it)
- Cohen, J. (1988). Statistical power analysis for the behavioral sciences (2nd ed.). Lawrence Erlbaum Associates.
- Cohen, J. (1992). A power primer. Psychological Bulletin, 112(1), 155–159. https://doi.org/10.1037/0033-2909.112.1.155
-
Kass, R. E., & Raftery, A. E. (1995). Bayes factors. Journal of the American Statistical Association, 90(430), 773–795.
https://doi.org/10.1080/01621459.1995.10476572
“these categories are not a calibration of the Bayes factor, but rather a rough descriptive statement about standards of evidence in scientific investigation” (Section 3.2, p. 777)
- Lee, M. D., & Wagenmakers, E.-J. (2014). Bayesian cognitive modeling: A practical course. Cambridge University Press. https://doi.org/10.1017/CBO9781139087759
- Jeffreys, H. (1961). Theory of probability (3rd ed.). Clarendon Press.
-
Lakens, D. (2013). Calculating and reporting effect sizes to facilitate cumulative science: A practical primer for t-tests and ANOVAs. Frontiers in Psychology, 4, 863.
https://doi.org/10.3389/fpsyg.2013.00863
“Cohen (1988) has provided benchmarks to define small (η2 = 0.01), medium (η2 = 0.06), and large (η2 = 0.14) effects.” (Eta-squared in between and within-subjects comparisons)
Spot an error? Something still confusing? Tell us at support@statsforpsychology.com.