Menu

StatisticsLive Code Editor
55 researchers ran this analysis this month

Wilcoxon Signed-Rank Test in Python

Technique overview

Compare paired measurements with a nonparametric test when the differences are not normally distributed.

The Wilcoxon signed-rank test compares paired measurements when the distribution of within-pair differences is not safely normal. It is appropriate for pre-post experiments, matched samples, left-right measurements, and repeated observations where each subject acts as their own control. A clear figure should show the pairing, not just two independent distributions, because the statistical evidence comes from the direction and size of each paired change.

Key points

  • Compare paired measurements with a nonparametric test when the differences are not normally distributed.
  • The Wilcoxon signed-rank test compares paired measurements when the distribution of within-pair differences is not safely normal.
  • It is appropriate for pre-post experiments, matched samples, left-right measurements, and repeated observations where each subject acts as their own control.
  • A clear figure should show the pairing, not just two independent distributions, because the statistical evidence comes from the direction and size of each paired change.
scipynumpymatplotlibseaborn

Example Visualization

Review the example first, then use the live editor below to run and customize the full workflow.

Mathematical Foundation

The Wilcoxon signed-rank test compares paired measurements when the distribution of within-pair differences is not safely normal.

W = sum of signed ranks for non-zero paired differences

Equation

W = sum of signed ranks for non-zero paired differences

Parameter breakdown

differenceAfter minus before for each matched pair
rankRank of the absolute non-zero difference
WTest statistic based on positive or negative signed ranks
p-valueProbability of observing rank imbalance this extreme under median difference = 0

When to use this technique

Use Wilcoxon signed-rank for paired, ordinal, or skewed continuous data. Use a paired t-test instead when paired differences are approximately normal.

Apply This Technique Now

Run this analysis workflow with AI in seconds. Use the prepared technique prompt or bring your own dataset.

View example prompt
Example AI Prompt

"Run a Wilcoxon signed-rank test on my paired data, plot the before-after distributions, and annotate the test statistic and p-value on the figure"

How to apply this technique in 30 seconds

1

Upload Data

Upload your CSV or Excel file in Analyze and keep your column names as-is.

2

Generate

Run the example prompt and let AI generate this technique automatically.

3

Refine and Export

Adjust code or prompt, then export publication-ready figures.

Implementation Code

The core data processing logic. Copy this block and replace the sample data with your measurements.

import numpy as np
from scipy import stats

np.random.seed(7)
before = np.random.lognormal(mean=1.4, sigma=0.35, size=24)
after = before * np.random.normal(loc=0.82, scale=0.16, size=24)

stat, p_value = stats.wilcoxon(before, after, zero_method="wilcox", alternative="two-sided")
diff = after - before
effect_r = stats.norm.isf(p_value / 2) / np.sqrt(np.count_nonzero(diff))

print(f"Wilcoxon W: {stat:.3f}")
print(f"p-value   : {p_value:.4f}")
print(f"median difference: {np.median(diff):.3f}")
print(f"effect size r: {effect_r:.3f}")

Visualization Code

Complete matplotlib code for a publication-ready figure. Copy, paste into your notebook, and adjust labels to match your data.

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

np.random.seed(7)
before = np.random.lognormal(mean=1.4, sigma=0.35, size=24)
after = before * np.random.normal(loc=0.82, scale=0.16, size=24)
stat, p_value = stats.wilcoxon(before, after)
diff = after - before

fig, ax = plt.subplots(figsize=(6, 5))
for i in range(len(before)):
    color = "#9240ff" if after[i] < before[i] else "#888888"
    ax.plot([0, 1], [before[i], after[i]], color=color, alpha=0.45, lw=1.2)
ax.scatter(np.zeros_like(before), before, color="#111111", s=28, label="Before")
ax.scatter(np.ones_like(after), after, color="#9240ff", s=28, label="After")
ax.set_xticks([0, 1])
ax.set_xticklabels(["Before", "After"])
ax.set_ylabel("Measurement")
ax.set_title("Paired Change with Wilcoxon Signed-Rank Test")
ax.text(0.5, max(before.max(), after.max()) * 1.04,
        f"W = {stat:.1f}, p = {p_value:.4f}\nmedian change = {np.median(diff):.2f}",
        ha="center", va="bottom", fontsize=9)
ax.spines[["top", "right"]].set_visible(False)
ax.legend(frameon=False)
plt.tight_layout()
plt.savefig("wilcoxon_signed_rank.png", dpi=300, bbox_inches="tight")
plt.show()

Visualize Differences Directly

A paired line plot shows subject-level movement, but a one-sample plot of the paired differences makes the signed-rank hypothesis easier to inspect.

fig, ax = plt.subplots(figsize=(5, 4))
ax.axvline(0, color="#888888", lw=1)
ax.boxplot(diff, vert=False, widths=0.35, showfliers=False)
ax.scatter(diff, np.random.normal(1, 0.03, size=len(diff)), color="#9240ff", s=24, alpha=0.75)
ax.set_xlabel("After - Before")
ax.set_yticks([])
ax.set_title("Distribution of Paired Differences")
plt.tight_layout()
plt.show()

Common Errors and How to Fix Them

Using Wilcoxon for independent groups

Why: The signed-rank test assumes matched pairs. Independent groups violate that pairing structure.

Fix: Use Mann-Whitney U for independent nonparametric two-group comparisons.

Many zero differences are present

Why: Ties at zero reduce the effective sample size and can make p-values less stable.

Fix: Report the number of zero differences and use scipy zero_method settings consistently.

Plot hides the matching

Why: Separate boxplots make paired data look independent.

Fix: Use paired lines or a paired difference plot so readers can see subject-level changes.

Frequently Asked Questions

Apply Wilcoxon Signed-Rank Test in Python to Your Data

Upload your dataset and Plotivy generates the Python code, runs the analysis, and produces a publication-ready figure.

Generate Code for This Technique

Python Libraries

scipynumpymatplotlibseaborn

Quick Info

Domain
Statistics
Typical Audience
Researchers analyzing matched samples, pre-post interventions, or repeated measurements with non-normal difference distributions

Apply to your data

Upload a dataset and get Python code instantly

Get Started Free