Parametric test assumptions: checks and fallbacks
The assumptions behind t-tests, ANOVA and regression, how to check each without the pre-test traps, and what to do when one fails, with a worked Welch ANOVA.
Updated . Written by Matt Gencer.
On this page
Parametric tests such as the t-test, ANOVA, Pearson’s correlation and linear regression are called parametric because they model the data with a distribution described by a few parameters, usually a normal distribution’s mean and standard deviation. They rest on a short list of assumptions: the observations are independent, the outcome is measured on a scale where means make sense, the thing the test averages is close enough to normally distributed, and, for some versions, the groups share one variance. Regression and correlation add linearity. The harder part is knowing which ones threaten your result, how to check them without making things worse, and what to do when a check fails.
This guide takes each assumption in turn, explains why testing assumptions before the main test is a weaker habit than it looks, gives a short simulation you can run, and works one example in full: Welch’s one-way ANOVA on Michelson’s 1879 speed-of-light measurements, run through a deterministic engine, where one assumption check fails, one passes without proving anything, and the most important assumption is one no check on the outcome can see.
The assumptions at a glance
| Assumption | What it means | How to look at it | If it fails |
|---|---|---|---|
| Independence | Each observation carries its own information; knowing one tells you nothing extra about another | The design: who or what was measured, when, and in what groups | Model the structure: paired tests, mixed models, cluster-robust errors |
| Measurement scale | The outcome is continuous, on an interval or ratio scale, so a mean is meaningful | The variable itself | Ordinal or count methods |
| Normality | The sampling distribution of the mean (or the residuals) is close to normal | Q-Q plot of residuals or within-group values; histograms | Larger samples help; robust, bootstrap or rank-based methods; a transformation that suits the scale |
| Equal variances | The groups have the same spread (Student’s t, classic ANOVA, ordinary regression) | Spread by group; residuals against fitted values | Welch’s t or Welch’s ANOVA; robust standard errors |
| Linearity | For correlation and regression, the relationship is a straight line | Scatter plot; residuals against fitted values | Transform, add terms, or a different model |
| No undue influence | No single value drives the result | Box plots; residual and influence plots | Check the value, run the analysis with and without it, report both |
Two things matter more than the rows: the assumptions are about the population and the design, not a sample passing a test, and they are not equally important. Glass, Peckham and Sanders put the useful question plainly in their 1972 review of ANOVA: not whether the assumptions are met exactly, which they never are, but whether the plausible violations have serious consequences for the conclusions. The rest of this guide is organised around that question.
Independence: the assumption no test can rescue
Independence comes first because a violation can do the most damage and no check on the outcome column can detect it. Every parametric test estimates how much its statistic would vary from sample to sample, and it does so by assuming each observation adds a fresh, separate piece of information. When observations are related, there is less information than the count suggests, the standard error comes out too small, and the p-value too small with it.
Common ways independence fails:
- Repeated measurements on the same units, such as several time points per participant or both eyes of one person, analysed as if each were a separate unit.
- Clustering: pupils in classes, patients in clinics, samples in batches, plants in plots. Units in one cluster share influences that units in other clusters do not.
- Order and time: measurements taken in sequence, where a drift in the instrument, the operator or the conditions makes neighbouring values more alike than distant ones.
- Pseudo-replication: several measurements of one experimental unit treated as several units, such as ten readings from one culture dish counted as ten dishes.
The check is a design question, not a statistical test: what was the unit that was randomised or sampled, and is every row in the analysis one of those units? If the answer is no, the fix is to analyse at the right level or model the dependence. Paired data get a paired test. Repeated measurements get a repeated-measures or mixed model; the repeated-measures ANOVA or mixed model guide explains the choice. Clustered data get a model with a cluster term or cluster-robust standard errors.
No transformation, rank test or variance correction repairs dependence: a Mann-Whitney test on clustered data has the same problem as a t-test on it.
Normality: of what, and how much it matters
The normality assumption is the most tested and the most misunderstood. Three points clear most of the confusion.
It is about the right quantity. A two-sample t-test needs the difference in means to be close to normally distributed. A one-way ANOVA needs the values within each group (equivalently, the residuals) to be roughly normal. A paired t-test needs the within-pair differences, not the two raw columns, to be roughly normal. Regression needs the residuals, not the outcome and not the predictors, to be roughly normal. Testing the pooled outcome of a multi-group study is the wrong check: if the groups differ, the pooled values are a mixture, and they can look non-normal even when every group is normal.
Sample size changes how much it matters. The sampling distribution of a mean approaches a normal distribution as the sample grows, whatever the shape of the data, which is the central limit theorem at work. Lumley and colleagues showed by simulation that the t-test and linear regression are valid for any outcome distribution in large samples, including very non-normal ones. How large is large depends on the shape, and no single number covers every case: the further the data are from normal, and especially when a few extreme values dominate, the more data the approximation needs. In small samples the assumption carries real weight, and that is exactly where it is hardest to check.
Extreme values matter more than shape. A mean and a variance are both sensitive to a few extreme observations. A sample can be mildly skewed with no consequence and yet be dominated by one value that is far from the rest. Before asking whether data are normal, ask whether any single value is driving the result, and whether that value is a genuine measurement or an error.
How to look: a normal Q-Q plot of the residuals (or of each group’s values) is the most informative single picture. Points along the line mean a near-normal shape; a bow signals skew; points peeling away at the ends signal heavy tails or a few extreme values. A Shapiro-Wilk test, introduced by Shapiro and Wilk in 1965, puts a p-value on the same question, with limits covered below. Ghasemi and Zahediasl report that it has more power than the Kolmogorov-Smirnov test, even with the Lilliefors correction, and treat any normality test as a supplement to the plot, not a replacement.
Equal variances: when it matters and when it does not
Student’s two-sample t-test and the classic one-way ANOVA pool the groups’ variances into a single estimate. That is correct only if the groups really share one variance. When they do not, how much it matters depends almost entirely on the group sizes.
With unequal sizes, the pooled tests can go wrong in either direction. Ruxton summarises published simulations of Student’s t-test from normal populations in which the false-positive rate was more than three times the nominal 5% when the larger variance went with the smaller sample, and less than a quarter of it when the larger variance went with the larger sample. The pooled estimate leans towards the larger group’s variance, so it understates the noise when the smaller group is noisier; the classic ANOVA pools the same way. With equal group sizes the distortion is much smaller, which the simulation below lets you see for yourself. Delacre, Leys, Mora and Lakens showed by simulation that under realistic differences in variance the classic F-test can give severely biased results, and they recommend Welch’s ANOVA by default when comparing means. Delacre, Lakens and Leys made the same case for Welch’s t-test over Student’s.
Welch’s versions estimate each group’s variance separately and adjust the degrees of freedom to match, so they do not assume equal variances at all. When the variances are in fact equal, they lose very little. That asymmetry is the argument for using them by default: the equal-variance check then informs, and does not choose your test. If you run one, Levene’s test is the usual choice: the NIST/SEMATECH handbook notes it is less sensitive than Bartlett’s test to departures from normality.
For regression, the same assumption is called homoscedasticity: the residual spread should not change with the fitted value, and a residuals-against-fitted plot that fans out is the usual sign of heteroscedasticity; the Breusch-Pagan test is the usual formal check. Logistic regression has a different list. The fixes are robust standard errors, a transformation, or a model whose variance changes with the mean; the Poisson or negative binomial guide covers counts.
The test-specific assumptions
A few assumptions belong to particular tests rather than to the whole family.
- Measurement scale. A test of means needs an interval or ratio scale. A t-test on a five-point rating is a statement about mean scores, which some audiences will not accept for an ordinal outcome.
- Linearity. Pearson’s correlation and linear regression measure a straight-line relationship. A strong curved relationship can give a weak correlation. Always plot first.
- Design-specific ones. Repeated-measures ANOVA adds sphericity, and ANCOVA adds equal covariate slopes across groups. Each has its own check and correction.
Should you test assumptions before the main test?
A common workflow runs Shapiro-Wilk and Levene’s test first and picks the main test from their p-values. It looks rigorous, but has three compounding problems.
Low power where it matters most. In small samples, assumption tests often fail to reject even when the assumption is false. Ghasemi and Zahediasl note that with small samples normality tests have little power, so small samples most often pass them. The pre-test is most likely to wave a problem through in exactly the situation where the main test is least robust to it.
Excess power where it matters least. In large samples, the same tests reject for departures far too small to affect the main test. The same paper notes that large samples give significant results even for small deviations from normality that will not affect a parametric test. A researcher who follows the gate abandons a valid analysis for a worse one.
A changed error rate for the test that follows. Choosing the main test from a pre-test on the same data makes the main test conditional on the pre-test result, and its error rate is no longer the one printed. For variances, Zimmerman found that running Levene’s test first and choosing Student or Welch from it fails to protect the significance level and usually makes the situation worse. For normality, Rochon, Gondan and Kieser found that a preliminary Shapiro-Wilk test seriously altered the conditional false-positive rates of both the t-test and the Mann-Whitney test that followed it, although in their scenarios the two-stage procedure as a whole stayed within acceptable limits. Schucany and Ng reached a sharper verdict for the one-sample t-test: a Shapiro-Wilk pretest did not correct the wrong significance levels it was meant to catch, made matters worse for exponential (skewed) data, and graphical diagnostics were the better tool.
Not detected is not confirmed. Even when a pre-test is run for information, its non-significant result says only that it did not detect a departure. A large p-value on Levene’s test is not evidence that the variances are equal, any more than a non-significant t-test is evidence that two means are equal; Greenland and colleagues list that reading among the common misinterpretations of p-values. Write “not detected”, never “confirmed” or “met”.
What to do instead:
- Decide from the design whatever you can: independence, pairing, clustering, the measurement scale.
- Use a robust default where one costs little: Welch’s t-test for two groups, Welch’s ANOVA for several.
- Look at the data: residual plots and spread by group, asking whether any departure is large enough, at this sample size, to matter.
- Report assumption tests for information if you run them, but do not let them choose the method.
- When in real doubt, run a sensitivity analysis: one alternative chosen in advance, reported beside the main result.
How much does a violation matter? A simulation you can run
The clearest way to see how much an assumption matters is to break it on purpose and count the false positives. The script below draws two groups from populations with the same mean, so every rejection is a false positive, and it does this many thousands of times. At a 0.05 level, a test that behaves as advertised rejects about 5% of the time.
# How often does each test reject a TRUE null hypothesis? Both groups below
# have the same population mean, so every rejection is a false positive.
set.seed(20261021)
n_sims <- 10000
alpha <- 0.05
false_positive_rate <- function(n1, n2, sd1, sd2, draw = rnorm) {
p <- replicate(n_sims, {
y1 <- draw(n1) * sd1
y2 <- draw(n2) * sd2
c(student = t.test(y1, y2, var.equal = TRUE)$p.value,
welch = t.test(y1, y2)$p.value)
})
rowMeans(p < alpha)
}
# 1. Unequal spread with unequal group sizes: the smaller group is noisier.
false_positive_rate(n1 = 10, n2 = 40, sd1 = 3, sd2 = 1)
# 2. The same spreads with equal group sizes.
false_positive_rate(n1 = 25, n2 = 25, sd1 = 3, sd2 = 1)
# 3. Skewed data (centred exponential), equal spread, at three sample sizes.
centred_exp <- function(n) rexp(n) - 1
for (n in c(10, 30, 100)) print(false_positive_rate(n, n, 1, 1, draw = centred_exp))
What to look for when you run it, and why:
- Scenario 1 is the case the equal-variance literature warns about: unequal sizes, with the larger spread in the smaller group. Expect Student’s rate to sit well above 5% and Welch’s to stay close to it.
- Scenario 2 keeps the same spreads but balances the sizes. Expect both tests to sit much closer to 5%, which is why balanced designs are forgiving.
- Scenario 3 uses clearly skewed data with the same shape in both groups and equal sizes. Expect both tests to stay fairly close to 5% even with 10 per group (Welch’s may sit a little below it at the smallest size), and closer as n grows. That is the central limit theorem at work, helped by the fact that identical skew in both groups largely cancels in the difference.
Change the numbers to match your own design. Two cautions apply. A simulation answers only the scenario it encodes, so a different shape in each group, or skew combined with unequal sizes, can behave worse than scenario 3. And the rate it prints is itself an estimate from a finite number of runs, so differences in the second decimal place are noise.
Worked example: Welch’s ANOVA on Michelson’s speed-of-light data
R ships a small dataset called morley: Albert Michelson’s measurements of the speed of light, made in 1879. According to R’s documentation, there are five experiments, each made of 20 consecutive runs, and each value is a speed measurement in kilometres per second with 299,000 subtracted. The documentation adds that the data can be viewed as a randomised block experiment, with experiment and run as the two factors, and that run can also be treated as a quantity to capture changes in the measurement over the course of an experiment.
The research question for the example is simple: does the mean measurement differ between the five experiments? If the apparatus and procedure were stable, all five experiments measured the same quantity and their means should differ only by chance; a difference would point to something systematic that changed between series.
Seeded and run in R; the method, Welch’s one-way ANOVA, was chosen before the run, not by a variance test. The full output and the R script appear below the article. The engine has reference pages for Welch’s ANOVA, the classic one-way ANOVA and the Kruskal-Wallis test.
The result
| Quantity | Value |
|---|---|
| Measurements analysed | 100 (five experiments of 20 runs) |
| Welch’s F | 3.006 on 4 and 47.04 degrees of freedom |
| p-value | 0.0274 |
| Eta-squared with its 95% interval (interval approximate: equal-variance model) | 0.1529 (0.02248 to 0.2667) |
| Games-Howell pairs with adjusted p below 0.05 | experiment 1 vs 4 (0.0207); experiment 1 vs 5 (0.0474) |
| Hedges’ g, experiment 1 vs 4 | 1.015 (0.3602 to 1.657) |
| Hedges’ g, experiment 1 vs 5 | 0.9095 (0.2634 to 1.545) |
Reading it
Welch’s F is 3.006 on 4 and 47.04 degrees of freedom, with p = 0.0274; the fractional degrees of freedom are Welch’s adjustment for unequal spread. At the 0.05 level the data are hard to reconcile with five equal means, provided the 100 runs can be treated as independent, a condition no check on the outcome can confirm, as the assumption checks below explain. That is all the omnibus test says: it does not say which experiments differ or by how much on its own.
The effect size puts a scale on it. Eta-squared is 0.1529: the experiment labels account for roughly 15% of the variation in the measurements. Its 95% interval runs from 0.02248 to 0.2667, so the data are compatible with anything from a small share to a substantial one. One caution: eta-squared is the ordinary ratio of between-group to total sums of squares, and its interval comes from the classic ANOVA model, which assumes equal variances. Welch’s adjustment changes the test, not this ratio, so read the interval as approximate.
The post-hoc comparisons locate the difference. The engine ran Games-Howell comparisons, the usual companion to Welch’s ANOVA because they also allow unequal variances, with a single-step adjustment for the ten pairs. Two pairs fall below 0.05 after adjustment: experiment 1 against experiment 4 (adjusted p = 0.0207) and experiment 1 against experiment 5 (adjusted p = 0.0474). The positive Hedges’ g values show experiment 1’s measurements running higher than both. In the engine’s letter summary, experiment 1 carries “a”, experiments 4 and 5 carry “b”, and experiments 2 and 3 carry both, so they are not distinguished from either side.
Look at experiment 1 against experiment 3 to see why the adjustment matters. Its Hedges’ g is 0.6751 with an interval from 0.04489 to 1.297, which excludes zero, yet its adjusted p is 0.211. The two are not in conflict. The g intervals are ordinary per-comparison intervals, with no allowance for running ten comparisons, and they use the pooled spread of the two groups. The adjusted p-values carry the allowance. The multiple comparisons guide explains why ten unadjusted looks at one dataset overstate the evidence.
Finally, the sensitivity figure. With five groups of 20, a one-way ANOVA at the 0.05 level reaches 80% power only for effects of Cohen’s f = 0.354 or larger. Detecting a conventional medium effect of f = 0.25 with 80% power would need 40 measurements per group. The engine computes this for the classic balanced ANOVA, which assumes normal data with equal variances, so for Welch’s test treat it as an approximation. It describes the design, not “observed power” calculated from this result: smaller differences between experiments could easily have been missed.
Reading the assumption checks
The engine ran two checks on the outcome and raised one descriptive note. None settles anything alone.
Normality by group (Shapiro-Wilk): failed in one experiment. In experiment 3, W was 0.837 with p = 0.0032, evidence that those 20 values are not normally distributed. In the other four experiments, the p-values were 0.0988, 0.167, 0.567 and 0.194: no departure detected, which, at 20 values each, is weak reassurance rather than confirmation. Because one group failed, the engine flagged the outcome as non-normal and suggested the rank-based alternative, the Kruskal-Wallis test.
Two things temper that flag. Five separate checks were run, so one failure by chance alone would not be surprising even if every experiment were normal. And with 20 values per group and a test of means, a departure confined to one group of five is the kind the central limit theorem tends to soften, unless it comes from a few extreme values. Neither point makes the failure meaningless. They make it a reason to look at experiment 3, not a reason to change the question.
Variance homogeneity (Levene): not detected. Levene’s statistic was 1.675 with p = 0.162, so the check did not detect unequal spread. The engine uses the median-centred form of Levene’s test. Brown and Forsythe found that versions of Levene’s test built on a more robust centre than the mean held their error rate under non-normality, and the NIST/SEMATECH handbook recommends the median version as a good general choice for non-normal data. “Not detected” is all this means. With 20 values per group the test has limited power, and the spreads can differ by a meaningful amount without a significant result. That is why this check was never allowed to choose the method: Welch’s ANOVA is valid whether or not the spreads are equal, so nothing here depends on the Levene result being right.
Extreme values: three flagged. The engine noted three measurements beyond Tukey’s interquartile-range fences and changed nothing. That convention is a prompt to check the values, not a definition of an error. A mean-based test is sensitive to them, so look first: which experiment are they in, and are they plausible measurements or slips? The engine’s note does not say; the code below shows where they sit.
Independence: the check that was not run. The documentation says each experiment is 20 consecutive runs. That raises the question this guide put first: are consecutive runs independent, or did conditions drift during a series so that neighbouring runs are more alike than distant ones? The engine’s checks look at the distribution of the outcome, so none of them can answer it. The documentation itself suggests treating run as a factor or as a trend within each experiment, which a one-way analysis of experiment alone ignores. If there is a drift, the one-way analysis leaves it in the residual spread, and if runs within an experiment are dependent, the standard errors are optimistic.
The diagnostic views the engine run does not draw take a few lines of base R:
m <- morley
m$Expt <- factor(m$Expt)
tapply(m$Speed, m$Expt, sd) # spread by experiment
fit <- aov(Speed ~ Expt, data = m)
qqnorm(residuals(fit)); qqline(residuals(fit)) # residual Q-Q plot
boxplot(Speed ~ Expt, data = m) # where the extreme values sit
with(m, plot(Run, Speed, col = Expt, pch = 19)) # drift across consecutive runs?
The Q-Q plot shows whether the experiment 3 failure is skew, a heavy tail or a few stray points.
What we did about the failed check
The engine suggested Kruskal-Wallis. The analysis keeps Welch’s ANOVA, for three reasons that generalise to most cases where a normality check fails.
First, the question is about means. Michelson’s experiments were attempts to measure one physical constant, and the natural question is whether their averages agree. Kruskal-Wallis tests whether values in some groups tend to be larger than in others, using ranks. That is a related but different question, and it equals a comparison of medians only if all five groups have the same shape and spread.
Second, the departure is limited: one group of five, 20 values each, under a test that leans on the sampling distribution of the means rather than on each raw value.
Third, a rank test would not touch what most likely matters here: possible dependence between consecutive runs, and run as an unmodelled factor.
The right response to the failed check is therefore a sensitivity analysis, not a silent switch. Run the alternative chosen in advance and report it beside the main result:
kruskal.test(Speed ~ factor(Expt), data = morley) # rank-based sensitivity check
If both analyses point the same way, the conclusion does not hinge on normality. If they disagree, say so, and report which question each one answered. In either case, the extreme values deserve a with-and-without comparison, reported openly, not a quiet deletion.
When an assumption fails: what to do, test by test
| Test | If independence fails | If normality is doubtful | If spreads differ |
|---|---|---|---|
| Two-sample t-test | Mixed model or a cluster-level analysis | Larger samples help; a transformation; Mann-Whitney (changes the question) | Welch’s t-test (the default anyway) |
| Paired t-test | Model the repeated structure | Wilcoxon signed-rank on the differences (changes the question) | Not applicable: one set of differences |
| One-way ANOVA | Mixed model or repeated-measures design | A transformation; Kruskal-Wallis (changes the question) | Welch’s ANOVA with Games-Howell comparisons |
| Pearson’s correlation | Account for the clustering | Spearman’s rank correlation | Look for a nonlinear pattern or extreme points |
| Linear regression | Mixed model or cluster-robust standard errors | Large samples help; a transformation; robust regression | Heteroscedasticity-robust standard errors; a model for the outcome type |
Two-group choices have their own guides: the t-test or Mann-Whitney guide and the paired t-test or Wilcoxon signed-rank guide. For three or more groups, the one-way ANOVA, Welch’s ANOVA and Kruskal-Wallis guide compares the three side by side. When the design has a second factor, as morley arguably does with run, the two-way ANOVA guide shows the model that includes it. For two independent groups, the t-tests explained post works a Welch’s t-test in full and reads its assumption checks, and the engine’s Welch’s t-test page lists its checks.
Two principles cut across the table. Fix the design problem before the distribution problem, because nothing else matters if independence fails. And prefer the fix that keeps your question, a robust version of the same test or a model for the outcome type, before a test that answers something else; if you do switch to a rank test, say the question changed.
Non-parametric is not assumption-free
Rank-based tests are often described as the safe option. They still assume independence, so they inherit every design problem a parametric test has. They assume the outcome can at least be ordered meaningfully. And they test a different hypothesis. The Mann-Whitney and Kruskal-Wallis tests ask whether values in one group tend to exceed values in another. Hart shows for the Mann-Whitney test that it responds to differences in spread and shape as well as location, and that it can be read as a comparison of medians only when the only difference between the groups is a shift. Kruskal-Wallis extends the same rank comparison to several groups, so the same caution carries over: read as a test of medians, it is correct only when the groups share one shape and spread.
They also discard the distances between values, a fair price for an ordinal scale and an unnecessary one for continuous data in a sample large enough for a mean-based test. Lumley and colleagues make the point directly: the main limitation of the t-test and linear regression is not a distributional one, but whether a difference in means answers the scientific question.
How to report assumption checks
A methods section needs a sentence or two, not a table of p-values. Say what you assumed from the design, what you checked and how, and what you did about anything that looked wrong. For the worked example:
Mean speed-of-light measurements were compared across Michelson’s five experiments (20 runs each) with Welch’s one-way ANOVA, chosen in advance because it does not assume equal variances, followed by Games-Howell comparisons. Shapiro-Wilk tests detected a departure from normality in experiment 3 (W = 0.837, p = 0.0032) and not in the other four; Levene’s test (median-centred) did not detect unequal variances (F = 1.675, p = 0.162). Three values lay beyond Tukey’s fences and were retained. Welch’s F(4, 47.04) = 3.006, p = 0.0274, eta-squared = 0.1529 (95% CI 0.02248 to 0.2667, from the equal-variance model and so approximate); experiment 1 differed from experiments 4 (adjusted p = 0.0207) and 5 (adjusted p = 0.0474). Runs within each experiment were consecutive, and the analysis does not model run order.
Once you have drawn the residual plots, add a sentence on what they showed; the engine run behind this example did not draw them, so the sentence above does not claim it.
Points to get right:
- Name the assumption checks as information, not as gates, and say the method was chosen before them.
- Write “not detected” for a non-significant check. Never “the data were normal” or “variances were equal”.
- Say what you did about a failed check: a sensitivity analysis, a with-and-without comparison, a transformation. If you did nothing, say why.
- Name the limitation the checks cannot reach, usually independence or an unmodelled factor.
Common mistakes
Treating a check as proof or as a gate. A non-significant check means a departure was not detected, and letting it pick the main test changes that test’s error rate. Choose a robust default from the design.
Switching to a rank test and keeping the conclusion about means. A Kruskal-Wallis result is not a statement about means, and it is a statement about medians only when the groups share one shape and spread.
Ignoring independence because nothing flagged it. No assumption check on the outcome can see dependence. Ask how the data were collected.
Saying a test “proves” an effect, or that you “accept the null”. A test shows whether the data are compatible with a hypothesis at a chosen level, in either direction. It proves nothing.
Rerunning the example
Below the article is the R script exactly as the engine generated it, with the seed and the bundled data path, and the output the engine printed. The script reads its data from a data/ folder holding a copy of R’s morley data; write.csv(morley, "data/parametric-test-assumptions.csv", row.names = FALSE) recreates that file. On the same package versions it reproduces the Welch test, the eta-squared value and its interval, the Games-Howell comparisons and the sensitivity figure. The Shapiro-Wilk and Levene checks, the extreme-value note and the pairwise Hedges’ g values come from the engine itself and are not in the script. Apart from the note, they can be recomputed with shapiro.test() within each experiment, car::leveneTest(Speed ~ factor(Expt), data = morley) and effectsize::hedges_g() on each pair.
The diagnostic plots and the Kruskal-Wallis call above are additions for you to run, and their output is not part of the engine’s record. To take the design further, add run to the model as the documentation suggests and compare the experiment differences with the ones above. The guide to reproducible statistical analysis explains what a reviewer needs to rerun a result like this one, and the guide to choosing a statistical test starts from the design when you are not sure which test applies.
Worked example
Data: Michelson AA (1882). Experimental determination of the velocity of light made at the U.S. Naval Academy, Annapolis. Astronomical Papers 1:109-145. As distributed in R's datasets package (morley). https://stat.ethz.ch/R-manual/R-devel/library/datasets/html/morley.html. Seed: 20261021.
Run on Celeus engine 0.30.0, seed 20261021, public data.
Output
# Results - Test: Welch's ANOVA - n: 100 - statistic: 3.006 - p-value: 0.0274 - effect size: eta-squared = 0.1529 (95% CI 0.02248 to 0.2667) (two-sided CI at the run's confidence level) - seed: 20261021 ## Assumption checks - normality by group (Shapiro-Wilk): passed=FALSE - variance homogeneity (Levene): passed=TRUE (no evidence of unequal variances) ## Post-hoc (Games-Howell; correction: single-step (Games-Howell)) - 1 vs 2: adj p = 0.313 | Hedges' g 0.6049 [-0.02132, 1.223] - 1 vs 3: adj p = 0.2115 | Hedges' g 0.6751 [0.04489, 1.297] - 2 vs 3: adj p = 0.9876 | Hedges' g 0.1525 [-0.4569, 0.7599] - 1 vs 4: adj p = 0.02073 | Hedges' g 1.015 [0.3602, 1.657] - 2 vs 4: adj p = 0.3599 | Hedges' g 0.5741 [-0.05044, 1.191] - 3 vs 4: adj p = 0.8037 | Hedges' g 0.3419 [-0.2725, 0.952] - 1 vs 5: adj p = 0.04736 | Hedges' g 0.9095 [0.2634, 1.545] - 2 vs 5: adj p = 0.6682 | Hedges' g 0.4155 [-0.2018, 1.027] - 3 vs 5: adj p = 0.9692 | Hedges' g 0.1951 [-0.4152, 0.8029] - 4 vs 5: adj p = 0.9729 | Hedges' g -0.1885 [-0.7962, 0.4217] groups: 1 (a), 2 (ab), 3 (ab), 4 (b), 5 (b) - groups sharing a letter are not significantly different at the adjusted threshold. ## Power (sensitivity, not observed power) - minimum detectable effect at n=100: Cohen's f = 0.3542 - to detect a conventional medium effect: 40 per group to detect f=0.25 - alpha = 0.05, target power = 0.8
R script
# Celeus - reproduce.R (run from this package folder; bundled data in data/)
# Test: Welch's ANOVA | engine 0.30.0 | catalog c39-d3cd
# Research context: not provided for this run.
# Reproduces the recorded result deterministically.
set.seed(20261021)
.data_path <- "data/parametric-test-assumptions.csv"
if (!file.exists(.data_path)) stop("Run reproduce.R from the package folder (the bundled data is in data/).")
data <- readr::read_csv(.data_path, show_col_types = FALSE) # needs the readr package
clean_cells <- function (df)
{
ctrl_collapse <- "[\r\n\t\v\f]+"
zero_width_chars <- intToUtf8(c(8203L, 65279L), multiple = TRUE)
uni_space_chars <- intToUtf8(c(160L, 8239L, 8199L), multiple = TRUE)
clean_text <- function(x) {
out <- x
for (ch in zero_width_chars) out <- gsub(ch, "", out,
fixed = TRUE)
out <- gsub(ctrl_collapse, " ", out)
for (ch in uni_space_chars) out <- gsub(ch, " ", out,
fixed = TRUE)
trimws(gsub(" +", " ", out))
}
changed_cols <- character(0)
cells_cleaned <- 0L
retyped <- character(0)
for (j in seq_along(df)) {
col <- df[[j]]
if (!is.character(col))
next
cleaned <- clean_text(col)
n_changed <- sum(!is.na(col) & !is.na(cleaned) & col !=
cleaned, na.rm = TRUE)
if (n_changed > 0L) {
changed_cols <- c(changed_cols, names(df)[j])
cells_cleaned <- cells_cleaned + n_changed
}
df[[j]] <- cleaned
non_blank <- cleaned[!is.na(cleaned) & nzchar(cleaned)]
if (length(non_blank) && all(grepl("^[+-]?(0|[1-9][0-9]*)([.][0-9]+)?$",
non_blank))) {
parsed <- suppressWarnings(as.numeric(cleaned))
was_blank <- is.na(cleaned) | !nzchar(cleaned)
lost <- (is.na(parsed) | is.infinite(parsed)) & !was_blank
if (!any(lost)) {
finite <- parsed[!is.na(parsed)]
all_whole <- all(finite == floor(finite))
in_range <- all(abs(finite) <= .Machine$integer.max)
df[[j]] <- if (all_whole && in_range)
as.integer(parsed)
else parsed
retyped <- c(retyped, names(df)[j])
}
}
}
names(df) <- clean_text(names(df))
if (length(changed_cols)) {
attr(df, "ingest_clean_columns") <- changed_cols
attr(df, "ingest_clean_cells_cleaned") <- cells_cleaned
}
if (length(retyped))
attr(df, "ingest_clean_retyped") <- retyped
df
}
data <- clean_cells(data)
# Complete-case analysis: drop rows missing any analysis value.
.acols <- c("Speed", "Expt")
data <- data[stats::complete.cases(data[, .acols, drop = FALSE]), , drop = FALSE]
result <- oneway.test(`Speed` ~ `Expt`, data = data, var.equal = FALSE)
print(result)
# Effect size (Eta2) and its confidence interval.
effect <- { .es_d <- data; .es_d[["Expt"]] <- as.factor(.es_d[["Expt"]]); .es_d[["Speed"]] <- .es_d[["Speed"]] - stats::median(.es_d[["Speed"]], na.rm = TRUE); effectsize::eta_squared(stats::aov(`Speed` ~ `Expt`, data = .es_d), partial = FALSE, ci = 0.95, alternative = "two.sided") }
print(effect)
# Post-hoc pairwise comparisons (Games-Howell; correction: single-step (Games-Howell)).
data[["Expt"]] <- as.factor(data[["Expt"]])
posthoc <- { .ph_d <- data; .ph_d[["Expt"]] <- as.factor(.ph_d[["Expt"]]); PMCMRplus::gamesHowellTest(`Speed` ~ `Expt`, data = .ph_d) }
print(posthoc)
# Sensitivity: minimum detectable effect at n=100 (power=0.8, alpha=0.05). NOT observed power.
power <- pwr::pwr.anova.test(k = 5, n = 20, sig.level = 0.05, power = 0.8)
print(power)Common questions
What are the assumptions of a t-test?
Independent observations, a continuous outcome on an interval or ratio scale, and an approximately normal sampling distribution for the mean or the difference in means. Student's two-sample version also assumes equal variances in the two groups; Welch's version drops that assumption, which is why it is the safer default.
What happens if the assumptions are violated?
It depends on which one and on the design. Dependent observations can make p-values far too small. Unequal variances matter most when group sizes also differ. Non-normal data matter most in small samples with skew or extreme values. The usual result is a false-positive rate that drifts away from the stated level.
Do I need to test normality first?
Not as a gate. A normality test has little power in small samples, where normality matters most, and flags trivial departures in large samples, where it matters least. Choosing the main test from its result also changes that test's error rate. Look at plots of the residuals and decide from the design and the data shape.
Does a non-significant Shapiro-Wilk or Levene test mean the assumption holds?
No. A non-significant result means the test did not detect a departure, not that the data are normal or the variances equal. With small groups these tests miss real departures often. Report the result as not detected and choose a method that stays valid if the assumption is off.
Does the normality assumption apply to the raw data or to the residuals?
To the residuals, or to the values within each group, not to the pooled outcome. In a paired t-test it is the within-pair differences; in regression it is the residuals, not the outcome or the predictors. A pooled outcome from groups with different means can look non-normal even when every group is normal.
Should I check normality with a plot or with a test?
Start with a plot, usually a normal Q-Q plot of the residuals, and treat a formal test as a supplement. If you do run one, Shapiro-Wilk has more power than the Kolmogorov-Smirnov test. A test cannot say whether a departure is large enough to matter at your sample size; the plot, read with the design in mind, comes closer.
Are non-parametric tests free of assumptions?
No. Rank-based tests still assume independent observations, and they answer a different question from the parametric test they replace: whether values in one group tend to be larger, rather than whether the means differ. They compare medians only when the groups' distributions have the same shape and spread, differing only by a shift.
Sources
- Welch BL (1951). On the comparison of several mean values: an alternative approach. Biometrika 38(3-4):330-336. doi:10.1093/biomet/38.3-4.330
- Delacre M, Leys C, Mora YL, Lakens D (2019). Taking parametric assumptions seriously: arguments for the use of Welch's F-test instead of the classical F-test in one-way ANOVA. International Review of Social Psychology 32(1):13. doi:10.5334/irsp.198
- Delacre M, Lakens D, Leys C (2017). Why psychologists should by default use Welch's t-test instead of Student's t-test. International Review of Social Psychology 30(1):92-101. doi:10.5334/irsp.82
- Zimmerman DW (2004). A note on preliminary tests of equality of variances. British Journal of Mathematical and Statistical Psychology 57(1):173-181. doi:10.1348/000711004849222
- Rochon J, Gondan M, Kieser M (2012). To test or not to test: preliminary assessment of normality when comparing two independent samples. BMC Medical Research Methodology 12:81. doi:10.1186/1471-2288-12-81
- Schucany WR, Ng HKT (2006). Preliminary goodness-of-fit tests for normality do not validate the one-sample Student t. Communications in Statistics - Theory and Methods 35(12):2275-2286. doi:10.1080/03610920600853308
- Ghasemi A, Zahediasl S (2012). Normality tests for statistical analysis: a guide for non-statisticians. International Journal of Endocrinology and Metabolism 10(2):486-489. doi:10.5812/ijem.3505
- Lumley T, Diehr P, Emerson S, Chen L (2002). The importance of the normality assumption in large public health data sets. Annual Review of Public Health 23:151-169. doi:10.1146/annurev.publhealth.23.100901.140546
- Glass GV, Peckham PD, Sanders JR (1972). Consequences of failure to meet assumptions underlying the fixed effects analyses of variance and covariance. Review of Educational Research 42(3):237-288. doi:10.3102/00346543042003237
- Shapiro SS, Wilk MB (1965). An analysis of variance test for normality (complete samples). Biometrika 52(3-4):591-611. doi:10.1093/biomet/52.3-4.591
- Brown MB, Forsythe AB (1974). Robust tests for the equality of variances. Journal of the American Statistical Association 69(346):364-367. doi:10.1080/01621459.1974.10482955
- Ruxton GD (2006). The unequal variance t-test is an underused alternative to Student's t-test and the Mann-Whitney U test. Behavioral Ecology 17(4):688-690. doi:10.1093/beheco/ark016
- Hart A (2001). Mann-Whitney test is not just a test of medians: differences in spread can be important. BMJ 323(7309):391-393. doi:10.1136/bmj.323.7309.391
- NIST/SEMATECH e-Handbook of Statistical Methods, section 1.3.5.10: Levene test for equality of variances. itl.nist.gov
- Greenland S, Senn SJ, Rothman KJ, Carlin JB, Poole C, Goodman SN, Altman DG (2016). Statistical tests, P values, confidence intervals, and power: a guide to misinterpretations. European Journal of Epidemiology 31(4):337-350. doi:10.1007/s10654-016-0149-3
Methods discussed
Try it on your own data
Upload a dataset and Celeus suggests a method, checks its assumptions, runs it in R, and gives you the script to rerun it.
Try it in Celeus