normality_test() checks whether numeric variables follow a normal
distribution, producing the two tests SPSS prints in its EXAMINE
"Tests of Normality" table:
Kolmogorov-Smirnov with Lilliefors significance correction (the "Kolmogorov-Smirnov(a)" column in SPSS)
Shapiro-Wilk (computed for n between 3 and 5000, matching the SPSS convention)
Use it before a t-test, ANOVA, or Pearson correlation to check the
normality assumption, together with levene_test for the
equal-variances assumption.
Arguments
- data
Your survey data (a data frame or tibble). If grouped (via
dplyr::group_by()), the tests are run separately per group — matching SPSSEXAMINE ... BY factor.- ...
Variables to test (unquoted, supports tidyselect). All selected variables must be numeric.
Value
An object of class "normality_test" whose $results
tibble holds one row per variable (and group combination) with:
- n
Number of valid (non-missing) cases
- ks_statistic, ks_df, ks_p
Kolmogorov-Smirnov statistic with Lilliefors-corrected p-value (Dallal-Wilkinson approximation); df equals n as in SPSS
- shapiro_w, shapiro_p
Shapiro-Wilk W and p-value (
NAwhen n < 3 or n > 5000)
Details
Understanding the Output
For both tests the null hypothesis is "the variable is normally distributed":
p >= 0.05: No significant deviation from normality detected.
p < 0.05: The variable deviates significantly from a normal distribution.
With large survey samples these tests flag even tiny, practically
irrelevant deviations. Combine them with the skewness and kurtosis
from describe before deciding against a parametric test.
When to Use This
Before
t_test,oneway_anova, orpearson_corto check the normality assumptionGrouped (via
group_by()) to check normality within each comparison group — the form of the assumption that actually matters for group comparisons
If normality is clearly violated, consider the rank-based
alternatives: mann_whitney, kruskal_wallis,
or spearman_rho.
Technical Details
The Lilliefors-corrected p-value uses the Dallal-Wilkinson (1986)
approximation, the same correction SPSS applies in EXAMINE
("Lilliefors Significance Correction"). Shapiro-Wilk uses
stats::shapiro.test() and is reported for 3 <= n <= 5000,
as in SPSS. Cases with missing values are excluded per variable.
Weights: normality_test() deliberately takes no
weights argument. Normality checks are a diagnostic of the
sample distribution, and neither Shapiro-Wilk nor the
Lilliefors correction has a well-defined fractional-frequency-weight
form. Run the test on the unweighted sample.
An SPSS v29 EXAMINE reference run is pending; until it lands the statistics are verified against independent R implementations of the same published formulas (see the SPSS compatibility vignette).
References
Dallal, G. E., & Wilkinson, L. (1986). An analytic approximation to the distribution of Lilliefors's test statistic for normality. The American Statistician, 40(4), 294-296.
See also
levene_test for the equal-variances assumption.
describe for skewness and kurtosis.
summary.normality_test for detailed output.
Other descriptive:
crosstab(),
describe(),
frequency(),
multiple_response()
Examples
library(dplyr)
data(survey_data)
# Test a single variable
normality_test(survey_data, age)
#> Normality Tests: age
#> age: KS = 0.028, p < 0.001; Shapiro-Wilk W = 0.990, p < 0.001 (n = 2500)
#> Use summary() for detailed output.
# Several variables at once
normality_test(survey_data, age, income, life_satisfaction)
#> Normality Tests: age, income, life_satisfaction
#> age: KS = 0.028, p < 0.001; Shapiro-Wilk W = 0.990, p < 0.001 (n = 2500)
#> income: KS = 0.079, p < 0.001; Shapiro-Wilk W = 0.963, p < 0.001 (n = 2186)
#> life_satisfaction: KS = 0.203, p < 0.001; Shapiro-Wilk W = 0.884, p < 0.001 (n = 2421)
#> Use summary() for detailed output.
# Within comparison groups (SPSS: EXAMINE ... BY gender)
survey_data %>%
group_by(gender) %>%
normality_test(age, income)
#> Normality Tests: age, income
#> 2 group combination(s) x 2 variable(s) [Grouped: gender]
#> Use summary() for detailed output.
# --- Three-layer output ---
result <- normality_test(survey_data, age, income)
result # compact overview
#> Normality Tests: age, income
#> age: KS = 0.028, p < 0.001; Shapiro-Wilk W = 0.990, p < 0.001 (n = 2500)
#> income: KS = 0.079, p < 0.001; Shapiro-Wilk W = 0.963, p < 0.001 (n = 2186)
#> Use summary() for detailed output.
summary(result) # full SPSS-style table
#>
#> Normality Tests Results
#> -----------------------
#> - Variables: age, income
#>
#> Tests of Normality
#> ------------------------------------------
#> Variable KS df KS p W W p
#> ------------------------------------------
#> age 0.028 2500 <.001 0.990 <.001
#> income 0.079 2186 <.001 0.963 <.001
#> ------------------------------------------
#>
#> KS = Kolmogorov-Smirnov statistic with Lilliefors significance correction.
#> W = Shapiro-Wilk statistic (computed for 3 <= n <= 5000, as in SPSS).
#> p < 0.05 indicates a significant deviation from normality.
