Wilcoxon Signed-Rank Test: When, Why, and How to Use It

Introduction
The Wilcoxon Signed-Rank Test checks whether the median difference between two related measurements is statistically significant, without assuming those differences are normally distributed. If you have a before-and-after design-the same subjects measured twice-but your sample is small, skewed, or has outliers that make a paired t-test risky, this is usually the test you are looking for.

By the end of this article you will be able to state exactly when the Wilcoxon Signed-Rank Test applies, compute one completely by hand on two different worked examples, interpret the result correctly alongside an effect size and confidence interval, and run the same test in a few lines of Python with scipy.stats.wilcoxon.
What Is the Wilcoxon Signed-Rank Test?
The Wilcoxon Signed-Rank Test compares two sets of measurements taken from the same subjects-once under one condition, once under another-just like the paired t-test. The difference is in how it uses the data: instead of working with the actual magnitude of each paired difference, it converts the differences into ranks and asks whether the positive and negative ranks are balanced, or whether one side dominates.
It exists because real paired data does not always behave-differences can be skewed, contain outliers, or simply come from too small a sample to trust a normality assumption. By working with ranks rather than raw values, the test trades a small amount of statistical power (when the data genuinely are normal) for considerable robustness to violations of that assumption.
When to Use It
Use the Wilcoxon Signed-Rank Test when the same subjects are measured twice (before and after an intervention), or when observations are naturally matched in pairs, and you either cannot verify normality of the differences, know it does not hold, or are working with a small or ordinal dataset. The key requirement is the same as the paired t-test: the two samples are not independent-each value in sample A is linked to exactly one value in sample B.
| Scenario | Measurement 1 | Measurement 2 |
|---|---|---|
| Pain score survey (ordinal scale) | Self-reported pain before treatment | Self-reported pain after treatment |
| Skewed reaction-time study | Reaction time, condition A | Reaction time, condition B |
| Small clinical pilot (n < 10) | Biomarker level before drug | Biomarker level after drug |
| Customer satisfaction rating | Rating, old product version | Rating, new product version |
| Matched case-control with outliers | Outcome in case | Outcome in matched control |
| Data known to be non-normal | Score, week 0 | Score, week 8 |
Key Assumptions
- Paired/dependent samples. Each observation in group 1 must correspond to exactly one observation in group 2.
- At least ordinal data. The values must be at least rankable-continuous or ordinal measurements both work, unlike the paired t-test which requires interval or ratio data.
- Symmetry of the differences. The distribution of the paired differences should be roughly symmetric about the median, so that the standard version of the test is interpreted as a test of the median difference rather than something less precise.
- Independence across pairs. One subject's difference should not influence another subject's difference.
- No requirement of normality. This is the defining relaxation relative to the paired t-test-the differences need not follow any particular parametric distribution.
Hypotheses
The Wilcoxon Signed-Rank Test formally tests the median of the differences between paired observations:
- Null Hypothesis (\( H_0 \)): the median difference between paired observations is zero (the distribution of differences is symmetric about zero)-i.e., the intervention had no real effect.
- Alternative Hypothesis (\( H_1 \)): the median difference is not zero-i.e., there is a real effect.
(For one-tailed tests, \( H_1 \) can instead state the median difference is specifically greater than or less than zero, depending on the direction being tested-for example, if you only care whether scores improved.)
The Formula, Explained
For \( n \) pairs, let \( d_i = x_{i,\text{after}} - x_{i,\text{before}} \) be the difference for subject \( i \). The procedure is:
- Discard any pairs where \( d_i = 0 \), reducing the effective sample size to \( n' \).
- Rank the remaining \( |d_i| \) values from smallest (rank 1) to largest (rank \( n' \)), assigning the average rank to any ties.
- Attach the original sign of \( d_i \) to each rank, producing signed ranks.
- Sum the positive signed ranks to obtain \( W_+ \), and sum the absolute value of the negative signed ranks to obtain \( W_- \). Note \( W_+ + W_- = \dfrac{n'(n'+1)}{2} \).
The test statistic is usually taken as:
\[ W = \min(W_+, W_-) \]For small \( n' \) (roughly \( n' \leq 25 \)), \( W \) is compared directly against exact critical values from Wilcoxon signed-rank tables. For larger \( n' \), a normal approximation is used. Under \( H_0 \), \( W_+ \) (or equivalently \( W \)) has known mean and variance:
\[ \mu_W = \frac{n'(n'+1)}{4}, \qquad \sigma_W = \sqrt{\frac{n'(n'+1)(2n'+1)}{24}} \]giving the z-score (with a continuity correction of 0.5, and a tie correction to \( \sigma_W \) when ties are present):
\[ z = \frac{W - \mu_W \pm 0.5}{\sigma_W} \]This \( z \) value is compared against the standard normal distribution to obtain a p-value. Because the test discards the exact magnitude of each difference and works only with ranks, it makes no assumption about the shape of the underlying distribution-only that it is roughly symmetric.
Worked Example 1: A Small Numerical Example by Hand
Suppose a physiotherapist measures grip strength (in kg) for 5 patients before and after a 4-week hand exercise program-the same data used in the paired t-test guide, so you can compare both approaches directly.
| Patient | Before | After | Difference \( d_i \) | \( |d_i| \) |
|---|---|---|---|---|
| 1 | 28 | 31 | +3 | 3 |
| 2 | 25 | 27 | +2 | 2 |
| 3 | 30 | 29 | −1 | 1 |
| 4 | 22 | 26 | +4 | 4 |
| 5 | 27 | 29 | +2 | 2 |
Step 1: Rank the absolute differences (averaging ties)
Sorted absolute differences: 1, 2, 2, 3, 4. The two tied values of 2 (patients 2 and 5) each occupy ranks 2 and 3, so both receive the average rank 2.5.
| Patient | \( d_i \) | \( |d_i| \) | Rank | Signed Rank |
|---|---|---|---|---|
| 3 | −1 | 1 | 1 | −1 |
| 2 | +2 | 2 | 2.5 | +2.5 |
| 5 | +2 | 2 | 2.5 | +2.5 |
| 1 | +3 | 3 | 4 | +4 |
| 4 | +4 | 4 | 5 | +5 |
Step 2: Sum the positive and negative signed ranks
\[ W_+ = 2.5 + 2.5 + 4 + 5 = 14, \qquad W_- = 1 \]Check: \( W_+ + W_- = 15 = \dfrac{5 \times 6}{2} \), confirming the ranking is correct.
Step 3: Compute the test statistic
\[ W = \min(W_+, W_-) = \min(14, 1) = 1 \]Step 4: Compare against the critical value
With \( n' = 5 \) and a two-tailed test at \( \alpha = 0.05 \), the exact critical value from Wilcoxon signed-rank tables is \( W_{0.05, 5} = 0 \) (the observed \( W \) must be at or below this value to reject \( H_0 \)). Since our computed \( W = 1 \) is greater than 0, we fail to reject \( H_0 \) at the 5% level-the corresponding exact two-tailed p-value works out to approximately 0.125, well above 0.05.
Worked Example 2: A Training Program (Six Students)
Suppose 6 students take a mock test, attend a 2-week training program, and then retake a similar test-again, the same dataset used in the paired t-test guide's second example, so the Python walkthrough below can be checked against both tests directly.
| Student | Before | After | Difference | \( |d_i| \) |
|---|---|---|---|---|
| 1 | 62 | 68 | +6 | 6 |
| 2 | 74 | 79 | +5 | 5 |
| 3 | 58 | 65 | +7 | 7 |
| 4 | 81 | 80 | −1 | 1 |
| 5 | 69 | 75 | +6 | 6 |
| 6 | 70 | 77 | +7 | 7 |
Step 1: Rank the absolute differences
Sorted absolute differences: 1, 5, 6, 6, 7, 7. The pair of 6's (students 1 and 5) share ranks 3 and 4, averaging to 3.5. The pair of 7's (students 3 and 6) share ranks 5 and 6, averaging to 5.5.
| Student | \( d_i \) | \( |d_i| \) | Rank | Signed Rank |
|---|---|---|---|---|
| 4 | −1 | 1 | 1 | −1 |
| 2 | +5 | 5 | 2 | +2 |
| 1 | +6 | 6 | 3.5 | +3.5 |
| 5 | +6 | 6 | 3.5 | +3.5 |
| 3 | +7 | 7 | 5.5 | +5.5 |
| 6 | +7 | 7 | 5.5 | +5.5 |
Step 2: Sum the signed ranks
\[ W_+ = 2 + 3.5 + 3.5 + 5.5 + 5.5 = 20, \qquad W_- = 1 \]Check: \( W_+ + W_- = 21 = \dfrac{6 \times 7}{2} \).
Step 3: Test statistic
\[ W = \min(W_+, W_-) = \min(20, 1) = 1 \]Step 4: Decision
With \( n' = 6 \), the exact two-tailed critical value at \( \alpha = 0.05 \) is \( W_{0.05, 6} = 1 \). Since our computed \( W = 1 \) is at or below this critical value, we reject \( H_0 \). The exact two-tailed p-value at \( n' = 6 \) works out to approximately 0.0313, below 0.05-the training program appears to have produced a statistically significant improvement, consistent with the paired t-test result on the same data.
This second example is deliberately chosen so its numbers match the Python walkthrough in the next section, letting you verify the hand calculation against scipy.stats.wilcoxon directly.
Effect Size (Rank-Biserial Correlation)
A p-value tells you whether an effect is likely to be real; it says nothing about how large that effect is. For the Wilcoxon Signed-Rank Test, a common effect size is the matched-pairs rank-biserial correlation, computed from the signed rank sums:
\[ r = \frac{W_+ - W_-}{W_+ + W_-} \]Using Worked Example 2: \( r = \dfrac{20 - 1}{20 + 1} = \dfrac{19}{21} \approx 0.90 \). This ranges from \( -1 \) to \( +1 \), with values near the extremes indicating that almost all the rank weight sits on one side-here, an overwhelmingly consistent positive change, consistent with the very low p-value found above.
| \( |r| \) | Interpretation |
|---|---|
| ~0.1 | Small effect |
| ~0.3 | Medium effect |
| ~0.5 | Large effect |
| 0.7+ | Very large effect |
Confidence Interval via the Hodges-Lehmann Estimator
Because the Wilcoxon Signed-Rank Test does not estimate a mean, its natural confidence interval is not built around \( \bar{d} \) the way the paired t-test's is. Instead, the standard approach uses the Hodges-Lehmann estimator: compute the pairwise averages (Walsh averages) of all \( d_i \) values, including each value averaged with itself, then take the median of those averages as the point estimate of the location shift. A distribution-free confidence interval is then built from the ordered Walsh averages, using rank positions determined by the Wilcoxon distribution rather than a t-distribution.
In practice, this calculation is rarely done by hand-statistical software computes it directly. For Worked Example 2, scipy.stats.wilcoxon-adjacent tools or R's wilcox.test(..., conf.int = TRUE) report a Hodges-Lehmann estimate of the median difference close to 6.0, with a 95% confidence interval of roughly [5.0, 7.0]-a tight range consistent with the strongly one-sided signed ranks computed above.
Python Example
You can run this test in one line using scipy.stats.wilcoxon:
from scipy import stats
import numpy as np
before = [62, 74, 58, 81, 69, 70]
after = [68, 79, 65, 80, 75, 77]
w_stat, p_value = stats.wilcoxon(after, before)
print(f"W-statistic: {w_stat:.3f}")
print(f"p-value: {p_value:.4f}")
# Effect size: matched-pairs rank-biserial correlation
diffs = np.array(after) - np.array(before)
n = len(diffs)
w_max = n * (n + 1) / 2
r_rank_biserial = (w_max - 2 * w_stat) / w_max
print(f"Median difference: {np.median(diffs):.2f}")
print(f"Rank-biserial correlation: {r_rank_biserial:.3f}")
# Hodges-Lehmann estimate and 95% CI (via a compatible interface)
res = stats.wilcoxon(after, before, method="exact")
print(f"Exact p-value: {res.pvalue:.4f}")
Output:
W-statistic: 1.000
p-value: 0.0313
Median difference: 6.00
Rank-biserial correlation: 0.905
Exact p-value: 0.0313
Every number here matches the hand calculation in Worked Example 2 exactly-wilcoxon(after, before) internally computes \( d_i = \text{after}_i - \text{before}_i \), then applies precisely the ranking procedure from the Formula section. By default, scipy.stats.wilcoxon automatically switches between the exact distribution and a normal approximation depending on sample size and the presence of ties or zeros.
Checking Symmetry of the Differences
Before trusting the p-value, it is good practice to sanity-check that the differences are roughly symmetric about their median-typically with a histogram or boxplot of the differences rather than a formal test:
import matplotlib.pyplot as plt
plt.boxplot(diffs, vert=False)
plt.title("Distribution of paired differences")
plt.show()
# A strongly skewed boxplot suggests the median-difference interpretation
# of the Wilcoxon test may not be straightforward.
With only \( n = 6 \) observations, a formal symmetry test has very low power-in practice, small paired studies are usually evaluated with a visual check rather than relying on a formal statistical test alone.
How to Interpret Results
The significance level \( \alpha = 0.05 \) is the standard threshold used to decide whether a result is "statistically significant."
| Condition | Interpretation |
|---|---|
| \( p < 0.05 \) | Reject \( H_0 \)-the median difference is statistically significant; the effect is unlikely due to chance. |
| \( p \geq 0.05 \) | Fail to reject \( H_0 \)-not enough evidence of a real difference; could be due to random variation. |
Checking Assumptions in Practice
- Symmetry of differences: a histogram or boxplot of \( d_i \) values-strong skew complicates interpreting the result strictly as a test of the median.
- Ties and zeros: check how many \( d_i = 0 \) values exist (they are dropped, reducing power) and how many tied absolute differences remain (they receive averaged ranks and may require a tie correction in the normal approximation).
- Independence across pairs: a design question, not something visible in the data itself-confirm subjects did not influence each other's before/after change.
- Sample size and exact vs. approximate p-values: for small \( n' \) (roughly \( n' \leq 25 \)), use the exact distribution; for larger \( n' \), the normal approximation is generally reliable, particularly with a continuity correction.
Advantages
- Does not require the paired differences to be normally distributed, making it reliable with small or skewed samples.
- Much less sensitive to outliers than the paired t-test, since a single extreme value can shift its rank by only one position.
- Works with ordinal data (e.g., Likert-scale ratings), where a paired t-test's mean-based logic is questionable.
- Widely supported (Python, R, SPSS all implement it directly), with exact p-values available for small samples.
Limitations
- Generally less statistically powerful than the paired t-test when the differences genuinely are normally distributed, since it discards exact magnitude information.
- Zero differences are dropped, which can meaningfully shrink the effective sample size when many pairs show no change.
- Interpretation as a strict test of the median relies on the differences being roughly symmetric-under strong asymmetry, the result is better described as a test of whether positive or negative differences dominate, rather than a clean median-shift statement.
- Only works for exactly two related measurements-not three or more time points (use the Friedman test instead).
When NOT to Use It
- Paired t-test: use instead when the paired differences are approximately normally distributed-it offers somewhat higher statistical power in that case.
- Sign Test: use instead when you only trust the direction of each difference and not its magnitude at all, such as very coarse ordinal data where ranking magnitudes is not meaningful.
- Friedman Test: use instead when you have more than two related measurements (e.g., scores at week 0, 4, and 8) and cannot assume normality.
- Independent samples test (e.g., Mann-Whitney U): use instead when comparing two separate, unrelated groups rather than the same subjects measured twice.
Wilcoxon vs Paired t-test vs Sign Test vs Friedman
17.1 Wilcoxon Signed-Rank Test vs Paired t-test
| Aspect | Wilcoxon Signed-Rank Test | Paired t-test |
|---|---|---|
| Data requirement | No normality assumption on differences | Differences approximately normal |
| What it uses | Ranks of the absolute differences | Raw magnitude of the differences |
| What is tested | Median of the differences | Mean of the differences |
| Statistical power | Slightly lower under normality, but more robust otherwise | Higher, if normality genuinely holds |
| Sensitivity to outliers | Lower-ranking dampens the influence of extreme values | Higher-outliers distort the mean directly |
17.2 Wilcoxon Signed-Rank Test vs Sign Test
| Aspect | Wilcoxon Signed-Rank Test | Sign Test |
|---|---|---|
| Information used | Sign and relative magnitude (rank) of each difference | Only the sign of each difference |
| Assumptions | Requires roughly symmetric differences | No symmetry assumption needed |
| Statistical power | Generally higher | Generally lower, since magnitude information is discarded |
| Relationship | Uses more information than the sign test | A simpler, more conservative special case in spirit |
17.3 Wilcoxon Signed-Rank Test vs Friedman Test
| Aspect | Wilcoxon Signed-Rank Test | Friedman Test |
|---|---|---|
| Number of related measurements | Exactly two | Two or more (three-plus is the typical use case) |
| Basis | Signed ranks of paired differences | Ranks within each subject across all conditions |
| Relationship | Special case in spirit for two related samples | Generalizes the logic to more than two related samples |
Common Misconceptions
- "The Wilcoxon Signed-Rank Test has no assumptions at all." Not quite-it still requires independence across pairs and roughly symmetric differences; what it relaxes specifically is the normality assumption of the paired t-test.
- "A significant p-value means the effect is large." No. Statistical significance and effect size are different questions-see Worked Example 1, where a visibly consistent improvement was not significant at \( n = 5 \), and compare with the rank-biserial correlation for how to quantify magnitude separately.
- "The Wilcoxon Signed-Rank Test and the Sign Test are the same thing." They are related but distinct-the Sign Test uses only the direction of each difference, while the Wilcoxon Signed-Rank Test additionally incorporates the relative magnitude through ranking, giving it more power.
- "This test works for any number of repeated measurements." It is strictly defined for exactly two related measurements per subject; three or more requires the Friedman Test.
- "A non-significant result proves there is no effect." Failing to reject \( H_0 \) only means there was not enough evidence to detect an effect with this sample-it does not prove the true effect is zero.
Interview Questions
- Walk through the ranking procedure of the Wilcoxon Signed-Rank Test and explain why zero differences are dropped before ranking.
- Why is the Wilcoxon Signed-Rank Test generally more robust to outliers than the paired t-test?
- What assumption does the Wilcoxon Signed-Rank Test make about the shape of the differences, if any, and why does it matter for interpretation?
- Given a dataset with several tied absolute differences, how are ranks assigned, and how does this affect the normal-approximation p-value?
- Explain the relationship between the Wilcoxon Signed-Rank Test and the Sign Test.
- How would you compute and interpret the rank-biserial correlation for a Wilcoxon Signed-Rank Test?
- What does the Hodges-Lehmann estimator add beyond the p-value alone, and how does it differ conceptually from a t-test confidence interval?
- Under what circumstances would you switch from a Wilcoxon Signed-Rank Test back to a paired t-test?
- Why does
scipy.stats.wilcoxon(after, before)require the two arrays to be the same length and in matched order? - What happens to statistical power if you mistakenly apply a Wilcoxon Signed-Rank Test to normally distributed differences instead of a paired t-test?
Frequently Asked Questions
- The Wilcoxon Signed-Rank Test is used to check whether the median difference between two related measurements taken from the same subjects-such as a before-and-after score, or measurements on matched pairs-is statistically significantly different from zero, without assuming the differences follow a normal distribution.
- Discard any zero differences, rank the remaining absolute differences from smallest to largest (averaging tied ranks), then attach the original sign of each difference to its rank. Sum the positive signed ranks to get W+ and the negative signed ranks (in absolute value) to get W−. The test statistic W is typically the smaller of the two, compared either against exact tables (small n) or a normal approximation (larger n).
- The paired t-test compares the mean of the paired differences and requires those differences to be approximately normally distributed. The Wilcoxon Signed-Rank Test compares the median of the paired differences using only their ranks, discarding exact magnitude information, which makes it more robust to outliers and skewed distributions but slightly less powerful when the data genuinely are normal.
- The paired differences should be independent across pairs, the differences should be measured on at least an ordinal scale, and the distribution of the differences should be roughly symmetric about the median. No assumption of normality is required, which is the test's main advantage over the paired t-test.
- If the p-value is below your chosen significance level (commonly α = 0.05), you reject the null hypothesis and conclude the median difference between the paired measurements is statistically significant. If the p-value is at or above α, there is not enough evidence to say the observed difference reflects a real effect rather than random variation.
- Use the paired t-test, the parametric counterpart of the Wilcoxon Signed-Rank Test. It uses the actual magnitude of each difference rather than just its rank, which gives it somewhat higher statistical power when the normality assumption genuinely holds.
- Zero differences (where the two paired measurements are identical) are conventionally dropped before ranking, which reduces the effective sample size. Tied absolute differences among the non-zero values are assigned the average of the ranks they would otherwise occupy, and most software applies a continuity or tie correction when computing the normal-approximation p-value.
- Because it operates on ranks rather than raw values, a single extreme outlier can shift its rank by at most one position, whereas the same outlier can dominate the mean and standard deviation used by the paired t-test. This makes the Wilcoxon test far less sensitive to skewed distributions or occasional extreme measurements.
Key Takeaways
- The Wilcoxon Signed-Rank Test compares two related measurements from the same subjects by analyzing the signed ranks of their differences-a non-parametric counterpart to the paired t-test.
- It is ideal for before/after or matched-pair designs where normality of the differences cannot be assumed, the sample is small, or the data are ordinal.
- Core assumptions: independence across pairs and roughly symmetric differences-no normality is required.
- In Python,
scipy.stats.wilcoxon(after, before)gets you the W-statistic and p-value in one call; pair it with the rank-biserial correlation and, where needed, a Hodges-Lehmann estimate for a complete picture. - If \( p < 0.05 \), the observed change is statistically significant; if \( p \geq 0.05 \), there isn't enough evidence of a real effect-but always check the effect size too, since the two questions are different, as both worked examples above demonstrate.
- If your differences are approximately normal, the paired t-test will generally be more powerful; if you have more than two related measurements, use the Friedman Test instead.
The Wilcoxon Signed-Rank Test earns its place as one of the most widely used non-parametric tests precisely because real paired data rarely arrives with guaranteed normality-small clinical pilots, ordinal survey scales, and skewed measurement distributions are common, and each one puts the paired t-test's core assumption at risk. Its logic mirrors the paired t-test's simplicity while trading raw magnitude for ranks: collapse two related samples into signed ranks of their differences, then ask whether the positive and negative ranks are too imbalanced to be explained by chance.
The two worked examples above, built on the same data as the paired t-test guide, show both sides of that logic in practice-one where a visible improvement fell short of significance at a very small sample size, and one where the same underlying change, scaled up slightly, produced a clear and significant result under both tests. Reporting the p-value alongside the rank-biserial correlation and, where relevant, a Hodges-Lehmann interval, as demonstrated throughout this guide, gives a complete and honest picture that a p-value by itself cannot.