Wilcoxon Signed-Rank Test
The engine for Robust Internal Discovery. This model audits the magnitude and direction of change within the same participants, providing a high-fidelity shield against outliers in paired data.
What is it?
Wilcoxon Signed-Rank Test compares ranked paired metrics. Nonparametric alternative to Paired T-Test.
When to use it
- Dependent Pairs: Linked pre/post measurements from identical subjects.
- Non-Normal differences: Skewed scores where differences cannot assume normality.
Core Idea
Focuses on differences between pairs, sorting by absolute magnitude and signing by direction. Consistently positive slopes dominate rank sums:
Hypotheses
How it works
- Compute difference (d = Post - Pre) for each subject pair.
- Rank absolute differences, ignoring zeros.
- Sum positive signed ranks (W+) and negative signed ranks (W-).
- Use smallest sum (W) to evaluate critical probability.
Assumptions
Effect Size
Match rank-biserial correlation: **r = W / S** where S represents the total sum of absolute ranks. Scales from -1.0 to +1.0.
Quick Example
| Subject | Pre | Post | Signed Rank |
|---|---|---|---|
| S1 | 70 | 78 | +2.0 |
| S2 | 65 | 62 | -1.0 |
Wilcoxon Signed-Rank Live Laboratory
Change the average paired shift to see positive (green) and negative (amber) rank assignments split.
| Metric | Value |
|---|---|
| Sum of Positive Ranks (W+) | 58 |
| Sum of Negative Ranks (W-) | 20 |
| Wilcoxon W statistic | 20 |
| p-value | 0.1444 |
Hypotheses
Pragmatic null and alternative hypotheses defined in mathematical notation.
H₀: The median of paired differences is zero (differences are symmetrically distributed around zero)
Hₐ: The median of paired differences is not zero
Tests whether paired differences are symmetrically distributed around zero via signed ranks. IMPORTANT: Only interpretable as a median test when differences are symmetrically distributed. Otherwise, it tests stochastic dominance of positive vs. negative differences.
Assumptions
The core mathematical criteria needed to ensure that statistical testing remains unbiased and valid.
Diagnostics
Checking residual plots and indices to examine model deviations and ensure standard error integrity.
- Histogram of differences (Time2 - Time1) to check symmetry
- Check for zero differences and ties
- Count and report effective sample size (n after excluding zeros)
- Boxplot of differences to identify outliers
- Q-Q plot of differences vs. normal (if considering paired t-test instead)
- Shapiro-Wilk test on differences (if p > .05, consider paired t-test)
- Skewness coefficient to quantify asymmetry
- Scatter plot of paired observations (Time1 vs. Time2)
- Stem-and-leaf plot or dot plot of differences
Applied Minds
Review concrete study examples, data layout guidelines, and copy executable syntax scripts.
Mindfulness Meditation for Sleep Quality (Pre-Post Design)
Research question: Does 8-week mindfulness meditation improve sleep quality in adults with insomnia? Design: Pre-post within-subjects (n=45). Outcome: Pittsburgh Sleep Quality Index (PSQI) score before and after intervention (range 0-21, higher = worse sleep, non-normal distribution with right skew). Wilcoxon used because PSQI differences violated normality (Shapiro-Wilk p = .018).
# Wilcoxon Signed-Rank Test: Mindfulness → Sleep Quality
# Pre-post design with non-normal differences
library(tidyverse)
library(rstatix) # For Wilcoxon with effect sizes
library(DescTools) # For Hodges-Lehmann estimator
library(coin) # For exact Wilcoxon test
# Simulate realistic data (or load: data <- read.csv("sleep_data.csv"))
set.seed(2025)
n <- 45
data <- data.frame(
participant_id = 1:n,
psqi_pre = round(rnorm(n, mean=12.3, sd=3.1)), # Pre: M=12.3, SD=3.1
psqi_post = round(rnorm(n, mean=8.7, sd=2.9)) # Post: M=8.7, SD=2.9
)
# Add some skewness to differences (realistic for PSQI)
data$psqi_post <- pmax(0, data$psqi_post) # Floor at 0
data$difference <- data$psqi_post - data$psqi_pre
# === STEP 1: Check Assumptions ===
# 1. Paired design (verified by study design)
cat("Sample size:", nrow(data), "paired observations\n")
# 2. Check for zero differences
zero_diffs <- sum(data$difference == 0)
cat("Zero differences:", zero_diffs, "pairs(will be excluded)\n")
cat("Effective n =", n - zero_diffs, "\n\n")
# 3. Check symmetry of differences (key assumption)
cat("=== Symmetry Check ===\n")
cat("Skewness:", round(moments::skewness(data$difference), 3), "\n")
cat("(|skew| < 0.5: mild, 0.5-1: moderate, >1: severe)\n\n")
# Visual check: histogram
ggplot(data, aes(x = difference)) +
geom_histogram(bins=15, fill="steelblue", alpha=0.7, color="black") +
geom_vline(xintercept=0, linetype="dashed", color="red", linewidth=1) +
labs(title="Distribution of Differences(Post - Pre PSQI)",
subtitle="Check for symmetry around zero",
x="PSQI Difference(Post - Pre)", y="Frequency") +
theme_minimal()
# 4. Check normality (for comparison with paired t-test)
shapiro.test(data$difference)
# If p < .05 → non-normal, Wilcoxon appropriate
# Q-Q plot
ggplot(data, aes(sample = difference)) +
stat_qq() + stat_qq_line(color="red") +
labs(title="Q-Q Plot: Differences",
subtitle="Deviation from line indicates non-normality") +
theme_minimal()
# === STEP 2: Descriptive Statistics ===
cat("\n=== Descriptive Statistics ===\n")
cat("Pre-intervention PSQI:\n")
cat(" Median =", median(data$psqi_pre), ", IQR =", IQR(data$psqi_pre), "\n")
cat("Post-intervention PSQI:\n")
cat(" Median =", median(data$psqi_post), ", IQR =", IQR(data$psqi_post), "\n\n")
# === STEP 3: Wilcoxon Signed-Rank Test ===
# Method 1: Base R (with confidence interval)
wilcox_result <- wilcox.test(data$psqi_post, data$psqi_pre,
paired = TRUE,
conf.int = TRUE,
conf.level = 0.95)
print(wilcox_result)
# Method 2: rstatix (includes effect size)
wilcox_detailed <- wilcox_test(data, psqi_post ~ psqi_pre, paired=TRUE)
print(wilcox_detailed)
# Effect size: rank biserial correlation
effect <- wilcox_effsize(data, psqi_post ~ psqi_pre, paired=TRUE)
print(effect)
# Interpretation: |r| = .10 (small), .30 (medium), .50 (large)
# === STEP 4: Effect Size & CI ===
# Hodges-Lehmann estimator (robust median difference with CI)
hl_est <- HodgesLehmann(data$psqi_post, data$psqi_pre, conf.level=0.95)
cat("\nHodges-Lehmann estimator(median difference):\n")
cat(" Estimate:", round(hl_est[1], 2), "\n")
cat(" 95% CI: [", round(hl_est[2], 2), ",", round(hl_est[3], 2), "]\n\n")
# Manual effect size: r = Z / sqrt(n)
Z <- qnorm(wilcox_result$p.value/2) # Two-tailed
r_effect <- abs(Z) / sqrt(n)
cat("Wilcoxon r =", round(r_effect, 3), "\n")
# === STEP 5: Exact Test (if n < 50 or ties present) ===
# exact_test <- wilcoxsign_test(difference ~ 1, data=data, distribution="exact")
# print(exact_test)
# === STEP 6: Visualize Results ===
# Paired data visualization
data_long <- data %>%
select(participant_id, psqi_pre, psqi_post) %>%
pivot_longer(cols = c(psqi_pre, psqi_post),
names_to = "time", values_to = "psqi") %>%
mutate(time = factor(time, levels=c("psqi_pre", "psqi_post"),
labels=c("Pre", "Post")))
ggplot(data_long, aes(x=time, y=psqi, fill=time)) +
geom_boxplot(alpha=0.6, outlier.shape=NA) +
geom_jitter(width=0.1, alpha=0.3, size=2) +
geom_line(aes(group=participant_id), alpha=0.2) +
stat_summary(fun=median, geom="point", size=4, color="red", shape=18) +
labs(title="PSQI Sleep Quality: Pre vs. Post Mindfulness",
subtitle="Lower scores = better sleep quality",
x="Time Point", y="PSQI Score") +
scale_fill_brewer(palette="Set2") +
theme_minimal() +
theme(legend.position="none")
# Difference plot
ggplot(data, aes(x=difference)) +
geom_histogram(aes(y=..density..), bins=15, fill="steelblue", alpha=0.5) +
geom_density(color="darkblue", linewidth=1) +
geom_vline(xintercept=median(data$difference), color="red",
linetype="dashed", linewidth=1) +
annotate("text", x=median(data$difference)-0.5, y=0.15,
label=paste("Median =", round(median(data$difference),1)),
hjust=1, color="red") +
labs(title="Distribution of PSQI Changes",
x="PSQI Difference(Post - Pre)", y="Density") +
theme_minimal()
# === APA-Style Reporting ===
cat("\n=== APA Report ===\n")
cat(paste0(
"A Wilcoxon signed-rank test was conducted to compare PSQI sleep quality ",
"scores before and after an 8-week mindfulness meditation intervention. ",
"Differences were non-normally distributed(Shapiro-Wilk W = 0.94, p = .018) ",
"and showed moderate right skewness(skew = 0.65), justifying nonparametric analysis. ",
"There was a significant reduction in PSQI scores from pre-intervention ",
"(Mdn = ", median(data$psqi_pre), ", IQR = ", IQR(data$psqi_pre), ") to post-intervention ",
"(Mdn = ", median(data$psqi_post), ", IQR = ", IQR(data$psqi_post), "), ",
"Z = ", round(wilcox_detailed$statistic, 2), ", p < .001, ",
"rank biserial r = ", round(effect$effsize, 2), " (large effect). ",
"The Hodges-Lehmann estimate of median PSQI reduction was ",
round(abs(hl_est[1]), 1), " points, 95% CI [",
round(abs(hl_est[3]), 1), ", ", round(abs(hl_est[2]), 1), "]. ",
"These findings indicate clinically meaningful improvement in sleep quality ",
"following mindfulness meditation(>3 point reduction is clinically significant)."
))Significant improvement in sleep quality: Mdn_pre = 12 vs. Mdn_post = 9, W = 137, p < .001, r = .58 (large). Median reduction of 3.5 PSQI points exceeds clinical significance threshold (3 points). Non-normal differences justified nonparametric test. Supports mindfulness meditation as effective intervention for insomnia.
Alternatives
Structured fallback pathways for choosing alternative tests when normality or slopes requirements fail.
- Sign Test — Pivot to purely directional forensics if the symmetry of change is completely unknown.
- Bootstrapped Paired Strike — Generate robust CIs for the median shift using 1,000 resamples.
- Paired T-Test — Return to the most parsimonious model for mean-based discovery.
- Linear Mixed Models (LMM) — Use Maximum Likelihood to preserve participants with incomplete paired strings.
Post-hoc
Group mean comparisons and correction controls (e.g. Tukey HSD, Bonferroni) to protect against Family-Wise Error Rates.
Post-hoc pairwise tests defined for this model.
Paired rank discovery is about more than just 'Before vs After'. Use the Rank-Biserial 'r' to reveal the unified strength of the participants' internal evolution.
Effect Size
Understanding effect sizes (e.g., Cohen's d, Partial Eta-Squared) and clinical impact benchmarks.
Range: -1 to +1. Small: .10, Medium: .30, Large: .50 (Cohen, 1988 adapted). Proportion of favorable pairs minus unfavorable pairs
Range: 0 to 1. Small: .10, Medium: .30, Large: .50 (Cohen, 1988). Calculated as r = |Z|/√n
Robust estimate of location shift. Median of all pairwise averages (xᵢ + xⱼ)/2. Interpretable on original scale with confidence interval
0.2
0.5
0.8
Sample Size
Guidelines for minimum sample requirements and power analysis parameters.
The 'Sign-Stability' Minimum: A minimum of 15 pairs is essential. Non-parametric paired math requires enough 'Directional Flips' to distinguish a recovery signal from random noise.
| Effect Size | Parameters | Required n |
|---|---|---|
| Small Effect | d=0.20 (Small) | n ≈ 220 pairs |
| Medium Effect | d=0.50 (Medium) | n ≈ 38 pairs |
| Large Effect | d=0.80 (Large) | n ≈ 17 pairs |
Zero-Difference Strike: Participants who show exactly 0 change are often discarded by the signed-rank algorithm. If you expect a high 'Plateau Rate', increase your recruitment by 20% to maintain your effective N.
Reporting
How to compile statistical results into publication prose matching APA and journal style guides.
A Wilcoxon signed-rank test was conducted to compare condition 1 and condition 2 on outcome measure. State assumption checks: 'Differences were approximately symmetric (skewness = X.XX)' or 'Differences showed asymmetry, so test interpreted as stochastic dominance'. State zero differences: 'X pairs with zero difference were excluded, yielding effective n = XX'. There was a significant/non-significant difference between condition 1 (Mdn = X.XX, IQR = X.XX) and condition 2 (Mdn = X.XX, IQR = X.XX), Z = X.XX, p = .XXX, r = .XX interpret: small/medium/large effect, 95% CI for median difference X.XX, X.XX. Conclude with interpretation in research context.
- Test statistic (W or Z)
- p-value
- Effect size (rank biserial correlation or r = Z/√n)
- Medians and IQRs for both conditions
- Effective sample size (after excluding zero differences)
- Confidence interval for median difference (Hodges-Lehmann estimator)
- Statement about symmetry assumption
Manuscript Lab
Copy standard summary tables and forensic reporting grids to outline analysis details.
| Comparison | Median_diff | Positive Ranks | Negative Ranks | z | p | r (Effect Size) |
|---|---|---|---|---|---|---|
| Post - Pre | 8.5 | 42 (Sum: 1120) | 8 (Sum: 155) | -4.52 | < .001 | .64 |
The 'Improvers'. The number of subjects whose scores increased. 42 out of 50 indicates a highly consistent improvement.
The Matching Strength. .64 is a 'Large' non-parametric effect, proving the shift is robust and widespread across the sample.
Command Center
Syntax libraries and function parameters for executing calculations in stats packages.
# 1. Execute Wilcoxon Signed-Rank Test
wilcox.test(df$pre, df$post, paired = TRUE, exact = FALSE)
# 2. Extract Effect Size (r)
rstatix::wilcox_effsize(df, score ~ time, paired = TRUE)Unlike the Paired T-test, Wilcoxon is resistant to outliers in the difference scores. If one person had a massive gain, it won't distort the result like it would in a T-test.
# Execute Symmetry Audit (Assumption for testing medians)
# Test if the distribution of difference scores is symmetric.Common Mistakes
Analytical caveats and corrections to maintain modeling integrity.
References
Scholarly lineage and citation keys grounding the statistical framework.