Mann Whitney U Test Calculator
Paste two groups of comma separated numbers or upload a CSV and get the U statistic, rank sums, the exact p value, the rank biserial effect size, the Hodges Lehmann median shift and four charts, plus a ready to paste APA sentence for your results chapter.
⚡ 0. Quick Answer
A Mann Whitney U test calculator compares two independent groups using ranks instead of means, so your data never has to be normally distributed.
Rank every value from both groups together, add the ranks inside group 1 to get R1, then subtract n1(n1 + 1) / 2. That is U1. The smaller of U1 and U2 is the reported U. A small U means one group sits almost entirely above the other. In the worked example on this page, U = 8.00 with n1 = n2 = 10, the exact p value is .0007, and the rank biserial effect size is .84, which is large.
Rule of thumb: if p is below .05 the two groups differ. Always report an effect size beside it, because with a large sample a trivial difference still produces a small p value.
💡 Key Takeaways
- The Mann Whitney U test is the non-parametric alternative to the independent samples t test, and it needs no normality assumption.
- It is mathematically identical to the Wilcoxon rank sum test, so U and W describe the same result.
- The statistic is U = min(U1, U2), and U ranges from 0, meaning no overlap at all, to n1 × n2 / 2, meaning complete overlap.
- Use the exact p value when both groups have 20 or fewer values and no ties, and the normal approximation with a tie correction otherwise.
- Report the rank biserial correlation as the effect size: about .10 is small, .30 is medium and .50 is large.
- It compares medians only when the two distributions have a similar shape. Otherwise it tests which group tends to produce larger values.
📚 1. What Is the Mann Whitney U Test?
The Mann Whitney U test answers one plain question: when you pick a value at random from group 1 and a value at random from group 2, is one of them reliably bigger than the other? It answers that without ever looking at the means. Instead it throws both groups into one pile, sorts them, and replaces every value by its position in that sorted pile. Those positions are the ranks. If one group holds most of the high ranks, the groups differ.
That single move, from values to ranks, is what makes the test so useful. A salary of 2 million and a salary of 200 thousand become rank 20 and rank 19. The extreme value stops dominating the answer. The same is true of ordinal data such as a 1 to 7 satisfaction scale, where the gap between 5 and 6 is not necessarily the same size as the gap between 1 and 2, so averaging is questionable but ranking is fine.
What the calculator reports:
- U1, U2 and U, the test statistic in all three forms so you can match any textbook or software output.
- Rank sums R1 and R2 and the mean rank of each group, which is what SPSS prints.
- Exact p value by full enumeration of the U distribution for small samples, and the normal approximation with tie correction for large ones.
- z score, with an optional continuity correction.
- Rank biserial correlation and r = z / √N, the two standard effect sizes.
- Common language effect size, the probability that a randomly drawn value from one group exceeds one from the other.
- Hodges Lehmann estimator, the median of every pairwise difference, which is the location shift the test is really estimating, with a confidence interval.
- Tie count and tie correction, plus a Noether sample size estimate for planning a replication.
A worked one-liner: with group 1 = 52, 48, 55, 61, 47, 50, 58, 53, 49, 56 and group 2 = 64, 59, 54, 66, 62, 57, 74, 60, 63, 69, the rank sums are R1 = 63 and R2 = 147. So U1 = 63 − 55 = 8, U2 = 100 − 8 = 92, and U = 8. The exact two tailed p value is .0007.
Who uses it: medical researchers compare pain scores and symptom scales between two treatment arms. Psychologists compare Likert responses between conditions. Ecologists compare counts between two sites where the data are heavily skewed. Education researchers compare exam performance between two teaching methods when class sizes are small. Economists compare income between two regions, where a few very high earners would wreck a t test.
Mann Whitney U test versus the nearest alternatives
| Test | Design | Compares | Use it when |
|---|---|---|---|
| Mann Whitney U | 2 independent groups | Rank distributions | Data are ordinal, skewed, or contain extreme values |
| Independent samples t test | 2 independent groups | Means | Data are roughly normal and interval or ratio |
| Welch t test | 2 independent groups | Means, unequal variance | Normal data but the two variances clearly differ |
| Wilcoxon signed rank | 2 paired measurements | Ranks of differences | The same people measured twice |
| Kruskal Wallis | 3 or more independent groups | Rank distributions | You have three or more groups to compare at once |
| Brunner Munzel | 2 independent groups | Stochastic dominance | The two distributions have clearly different shapes or spreads |
🧮 2. Set Up Your Data
Type one value per cell. Each column becomes a cluster. Empty cells are ignored.
📊 3. Results
🧠 4. Interpretation of Results, In Detail
4.1 What the U statistic actually counts
U is a counting statistic, not an average of anything. U1 counts how many times a value in group 1 beats a value in group 2 across every possible pairing, with a tie counted as half a win. If group 1 has 10 values and group 2 has 10 values there are 100 pairings, so U1 can range from 0 to 100. U1 = 0 means group 1 lost every single comparison. U1 = 100 means it won every one. U1 = 50 is the perfectly balanced middle.
That is why U carries information the p value does not. A U of 8 out of a possible 100 tells you the separation is nearly total. A U of 44 out of 100 tells you the groups are barely distinguishable, no matter what the p value says.
4.2 Reading the p value correctly
The p value is the probability of getting a U at least as extreme as yours if the two groups really came from the same distribution. It is not the probability that the groups are the same, and it is not the probability that you are wrong. A p of .0007 means: if there were truly no difference, a separation this clean would show up in about 7 samples out of every 10,000.
Compare p against your alpha, which is normally .05. If p is smaller, you reject the null hypothesis of no difference. If p is larger, you fail to reject it, which is not the same as proving the groups are identical. A non-significant result with a small sample most often means you did not have enough data to detect anything, not that nothing is there.
4.3 Exact versus approximate p values, and why they differ
For small samples this calculator enumerates the complete distribution of U by dynamic programming, so the exact p value is the true probability with no approximation involved. For larger samples it standardises U into a z score and reads the normal curve. The two will not agree to the last decimal, and the exact value is the one to quote whenever it is available.
In the worked example the exact p is .0007 while the normal approximation gives .0017. Both lead to the same decision, but they are not interchangeable in a write up. When ties are present the exact calculation is no longer valid, because the tie changes the set of possible rank arrangements, so the calculator automatically falls back to the corrected normal approximation and tells you it did.
4.4 The effect size is the part reviewers actually read
A p value tells you whether a difference is detectable. An effect size tells you whether it matters. The rank biserial correlation r_rb runs from minus 1 to plus 1 and has a beautifully direct reading: it is the probability that a group 1 value beats a group 2 value minus the probability of the reverse. An r_rb of .84 means group 1 wins 92 percent of the pairwise comparisons and loses 8 percent.
| |r_rb| | Label | What it looks like in practice |
|---|---|---|
| 0.00 to 0.10 | Negligible | The two groups are almost completely interchangeable |
| 0.10 to 0.30 | Small | A real but faint tendency, only visible with a decent sample |
| 0.30 to 0.50 | Medium | Clearly visible in a box plot, worth reporting as a finding |
| 0.50 to 0.70 | Large | The distributions barely overlap |
| 0.70 and above | Very large | One group sits almost entirely above the other |
The second effect size, r = z divided by the square root of N, is the one many journals still expect. It is not identical to r_rb and will usually be a little smaller. Report whichever your field expects, and say which one you used.
4.5 The common language effect size, for non-statisticians
The common language effect size, sometimes written CLES or the probability of superiority, is U1 divided by n1 times n2. It answers a question anyone can follow: if you pick one person at random from each group, what is the chance the group 1 person scores higher? A CLES of .92 means 92 times out of 100. This is the single most useful number to put in an abstract or a slide for a non-technical audience.
4.6 The Hodges Lehmann estimator, the size of the shift
People often want to know how big the difference is in the original units, not in ranks. The Hodges Lehmann estimator gives you that. It takes every possible pair of one value from each group, calculates the difference, and reports the median of all those differences. It is the location shift the Mann Whitney U test is genuinely estimating, and it is far more robust than the difference between the two sample medians.
The calculator also gives a distribution free confidence interval around it, built from the ordered pairwise differences. If that interval excludes zero, the result is significant at the matching alpha, which is a useful cross check on the p value.
4.7 Medians, or something subtler?
This is the most misunderstood part of the test, and it is worth getting right. The Mann Whitney U test compares medians only if you are willing to assume the two distributions have the same shape and spread, and are simply shifted relative to each other. That assumption is often reasonable and rarely checked.
If the shapes clearly differ, for example one group is tightly clustered and the other is widely spread, the test still works but it is testing something broader: whether values from one group tend to be larger than values from the other. Two groups can share an identical median and still give a highly significant Mann Whitney result, because the test is sensitive to the whole distribution. When the shapes differ badly, say so in your write up, or switch to the Brunner Munzel test.
4.8 What the mean ranks tell you
SPSS reports mean ranks rather than U, which confuses people moving between packages. The mean rank of a group is its rank sum divided by its sample size. Under the null hypothesis both mean ranks should sit near (N + 1) / 2, where N is the combined sample size. In the worked example N = 20, so the expected mean rank is 10.5, and the observed values of 6.3 and 14.7 sit a long way either side of it. That distance is the effect, expressed in the units the test actually works in.
4.9 Ties, and what they cost you
Ties are values that appear more than once across the pooled sample. They are unavoidable with Likert scales, rounded measurements and small integer counts. Each tied group gets the average of the ranks it spans, which shrinks the variance of U. The tie correction restores the right variance, and without it your p value would be too large, meaning you would miss real effects.
Heavy ties are a signal, not just a nuisance. If more than about a quarter of your values are tied, your measurement is coarse relative to the differences you are hunting, and no test will rescue that. Consider a finer scale, or an ordinal regression model that treats the categories properly.
4.10 A decision guide for what to do next
| What you are looking at | What it means | What to do |
|---|---|---|
| p < alpha and |r_rb| ≥ .30 | A real and meaningful difference | Report it, quote the Hodges Lehmann shift in original units, and plot it |
| p < alpha but |r_rb| < .10 | Detectable only because the sample is large | Report it honestly as a trivial difference. Do not headline it |
| p ≥ alpha and n is small | Underpowered, not evidence of no effect | Report the confidence interval, do not claim equivalence, plan a bigger study |
| p ≥ alpha and n is large | Genuinely little to find | Report the interval and consider a formal equivalence test |
| Distribution shapes clearly differ | Not a clean median comparison | Report it as stochastic dominance, or switch to Brunner Munzel |
| More than 25 percent ties | The measurement is too coarse | Use ordinal regression, or refine the measurement scale |
4.11 Common mistakes this calculator prevents
- Reporting the wrong U. SciPy returns U1, R returns W, SPSS returns the smaller U. The calculator prints all three so you can never quote a mismatched pair of numbers.
- Skipping the tie correction. Doing the normal approximation by hand without it inflates the p value. It is applied automatically here.
- Using the normal approximation on tiny samples. With five per group it is unreliable. The calculator switches to the exact method for you.
- Calling it a median test with no shape check. The assumption panel checks the two spreads and warns you when a median interpretation is not safe.
- Reporting p alone. Every run prints two effect sizes and the shift in original units.
- Halving a two tailed p to fake a one tailed test. The alternative hypothesis is chosen before you run it, and the output states which one you used.
4.12 How confident should you be?
The Mann Whitney U test is powerful, but it is one test on one sample. A p value just under .05 in a study of ten people per group is weak evidence, whatever the asterisk implies. A clean separation with a large effect size, replicated in a second sample, is strong evidence. Read the confidence interval on the Hodges Lehmann shift: if it stretches from a trivial difference to an enormous one, your study simply has not pinned the effect down yet, and that is the honest thing to write.
✍ 5. How to Write Your Results in Research
Five templates, one for every place a Mann Whitney U test normally lands. Run the analysis and each one fills with your own numbers, ready to copy. Before you run it, they show the worked example so you can see the shape of a correct sentence.
APA conventions to keep
- Report medians, never means, because this test does not use means.
- Italicise U, z, p, n and Mdn in the final typeset text.
- Drop the leading zero on p and on r_rb, because both cannot exceed 1.
- Write p < .001 rather than p = .000. A p value is never exactly zero.
- Give the exact p to three decimals whenever it is above .001.
Thesis conventions to keep
- Justify why you chose a non-parametric test before you report it.
- State how ties were handled and how many there were.
- Give mean ranks as well as U, because examiners often expect the SPSS style output.
- Say explicitly which p value method was used, exact or approximate.
Plain language conventions to keep
- Use the common language effect size, since it is the only one a general reader can picture.
- Give the difference in original units, not in ranks.
- Avoid the words significant, null hypothesis and p value entirely.
- Translate the p value into a frequency, such as fewer than 1 in 1000.
Poster conventions to keep
- Give the interquartile range beside every median, because a median alone hides the spread.
- Keep it to three sentences: methods, results, conclusion.
- Label the effect size in words as well as numbers.
Pre-registration conventions to keep
- Fix the alternative hypothesis in advance. Choosing one tailed after seeing the data is not allowed.
- State the p value method and the tie handling before you collect anything.
- Name the effect size you will report, so you cannot pick the flattering one later.
- Give the sample size justification and the power target.
∑ 6. Formulas Used
Seven cards, each one step further from the raw ranks. Card 1 is the statistic itself, and every card after it builds on the one above.
📝 7. How to Use This Calculator
- Check your design. You need one numeric or ordinal outcome measured on two groups of different people, animals, plots or items. If the same subjects were measured twice, use the Wilcoxon signed rank test instead.
- Name the groups. Click the title box on each cluster and type a real name, for example Placebo and Treatment. Those names appear on every chart, in the results table and in the copied write up.
- Enter the data. Paste your values into each group box, comma separated:
52, 48, 55, 61, 47, .... Spaces, tabs and new lines all work too, so a column pasted straight from a spreadsheet is fine. - Or upload a file. Open the Upload tab, choose a CSV or Excel file, then click the columns that should each become a cluster. Selected columns are loaded as separate clusters and appear in the group dropdowns.
- Pick which two clusters to compare. If you loaded more than two, use the Group 1 and Group 2 dropdowns to choose the pair.
- Set the alternative hypothesis. Two tailed is the default and the right choice unless you predicted a direction before collecting any data.
- Set alpha. Leave it at 0.05 unless your protocol, journal or supervisor says otherwise.
- Leave the p value method on Automatic. The calculator uses the exact enumeration when both groups have 20 or fewer values and no ties, and the tie corrected normal approximation otherwise.
- Press Run Mann Whitney U Test. Read the verdict badge first, then the effect size, then the Hodges Lehmann shift in your own units.
- Copy your write up. Scroll to section 5, pick the template that matches where the result is going, and press Copy. Use Download Doc or Download PDF for the full record.
📈 8. How to Do a Mann Whitney U Test in Excel
Excel has no MANNWHITNEY function and the Analysis ToolPak does not include this test either, so you build it from five ordinary formulas. It takes about three minutes. Every screenshot below uses the same worked example as sections 9, 10 and 12, so all four agree on U = 8.00 and an exact p of .0007.
8.1 The Excel functions you need
| Function | What it does here | Example |
|---|---|---|
RANK.AVG | Ranks the pooled column and gives tied values their average rank | =RANK.AVG(B2,$B$2:$B$21,1) |
SUMIF | Adds the ranks belonging to one group, giving R1 and R2 | =SUMIF($A$2:$A$21,"Placebo",$C$2:$C$21) |
COUNTIF | Counts each group, giving n1 and n2 | =COUNTIF($A$2:$A$21,"Placebo") |
NORM.S.DIST | Turns the z score into a p value from the standard normal curve | =2*NORM.S.DIST(-ABS(F13),TRUE) |
MEDIAN | Reports each group median, which is what you actually write up | =MEDIAN(B2:B11) |
SQRT | Builds the standard deviation of U | =SQRT(F4*F5/12*(F4+F5+1)) |
SUMPRODUCT | Builds the tie correction term in one cell | See 8.3 |
RANK.AVG, not RANK or RANK.EQ. The older functions give tied values the same lowest rank, which breaks the rank sums and quietly gives you the wrong U.8.2 Step by step
1 Stack your data in long format
Put the group label in column A and the value in column B, one observation per row. Do not put the two groups side by side, because RANK.AVG has to rank both groups together against one pooled range.
The two groups stacked in one column. Twenty rows in total, rows 2 to 21, with Placebo in rows 2 to 11 and Treatment in rows 12 to 21.
2 Rank the pooled values
In C2 enter the ranking formula and fill it down to C21. The third argument, 1, means rank ascending so the smallest value gets rank 1.
Value 52 takes rank 5, value 47 takes rank 1 and value 66 takes rank 18. The dollar signs lock the pooled range so it does not shift as you fill down.
3 Add the ranks in each group
Now build a small summary block off to the right. F2 holds R1, F3 holds R2, F4 and F5 hold the two sample sizes.
=SUMIF($A$2:$A$21,"Placebo",$C$2:$C$21) =COUNTIF($A$2:$A$21,"Placebo")R1 = 63 and R2 = 147. Always add them: 63 + 147 = 210, which must equal N(N + 1) / 2 = 20 × 21 / 2. If it does not, a rank is wrong.
4 Convert the rank sums into U
Two more cells. U1 comes from R1, and U2 is whatever is left over out of n1 times n2.
=F2-F4*(F4+1)/2 =F4*F5-F7U1 = 63 − 55 = 8.00 and U2 = 100 − 8 = 92.00. The reported U is the smaller of the two, so U = 8.00. The check U1 + U2 = 100 confirms the arithmetic.
5 Get the p value
Build mu, sigma and z, then read the normal curve. With no ties, sigma is the simple form.
=F4*F5/2 =SQRT(F4*F5*(F4+F5+1)/12) =(ABS(F9-F11)-0.5)/F12 =2*NORM.S.DIST(-ABS(F13),TRUE)mu = 50.0000, sigma = 13.2288, z = −3.1371 and the two tailed p = 0.0017. The exact p from full enumeration is 0.0007, and with only ten per group that is the value you should report.
8.3 The awkward cases
When you have ties. The simple sigma is too large, so the p value comes out too conservative. Replace it with the tie corrected version. Put the count of each distinct value in a helper column with COUNTIF, then use:
where H holds the tie group sizes. It is fiddly, and it is the main reason people give up on Excel for this test.
When your groups are in two side by side columns. You cannot rank them properly that way. Restack them into long format first: copy group 2 underneath group 1 in column B and type the labels into column A.
When a group name has a trailing space. SUMIF will silently return 0 and your R1 will be wrong. Wrap the criteria in TRIM, or use Find and Replace to clean the labels first.
When you want the exact p value. Excel cannot do it without a macro. Use this calculator, or R, or Python. For n1 and n2 both at or below 20 the exact value is materially different from the approximation, as this example shows.
8.4 Why Excel, R and Python can disagree
| Difference | Excel | R wilcox.test | Python mannwhitneyu |
|---|---|---|---|
| Statistic reported | Whatever you build, usually min(U1, U2) | W, which equals U1 for the first level | U1 for the first argument |
| Exact p value | Not available | Default when n < 50 and no ties | Default when n ≤ 8, otherwise ask for method="exact" |
| Continuity correction | You add the 0.5 yourself | On by default, correct = TRUE | On by default, use_continuity=True |
| Tie correction | Manual, and often skipped | Automatic | Automatic |
| Behaviour with ties | Silently wrong if you forget | Warns and switches to the normal approximation | Switches to the normal approximation |
8.5 Charting it in Excel
A Mann Whitney result is best shown as a box plot, because the test is about the whole distribution rather than one summary number. In Excel 2016 and later, select both value columns, then Insert, Statistic Chart, Box and Whisker. Excel draws the median as the line inside the box, which is exactly what you should be discussing. Add the individual points on top by inserting a scatter series with a small horizontal jitter, so a reader can see the sample size at a glance. Do not use a bar chart of means: it hides the very skew that made you choose this test.
8.6 Error messages and what they mean
| What you see | Cause | Fix |
|---|---|---|
#N/A from RANK.AVG | The cell is text, not a number | Use Text to Columns, or multiply the column by 1 to force numbers |
#VALUE! | A blank or a stray character inside the ranked range | Shrink the range to the filled rows, or clean the blanks |
| SUMIF returns 0 | Group label mismatch, usually a trailing space | Wrap the criteria in TRIM, or retype the labels |
| R1 + R2 does not equal N(N+1)/2 | The ranked range does not cover every row | Check the $B$2:$B$21 range covers all N rows |
| p value greater than 1 | The two tailed doubling was applied to a p already above .5 | Cap it at 1, or use =MIN(1,2*NORM.S.DIST(...)) |
| Negative U | n1 was taken from the wrong group | Make sure the n in the U1 formula matches the group whose ranks you summed |
📈 9. How to Do a Mann Whitney U Test in R
R has the test built in as wilcox.test, because R uses the Wilcoxon rank sum name. The one liner is wilcox.test(x, y). The script below does the full job: the test, both p value methods, the effect sizes, the Hodges Lehmann shift, a plain English verdict and one 300 dpi figure. It uses base R only, so nothing needs installing.
9.1 The complete script
R · runs top to bottom, change only the two data lines
# Mann Whitney U test in R (also called the Wilcoxon rank sum test)
# Base R only. install.packages("effsize") is optional, the effect size is computed by hand below.
set.seed(42)
# ---- 1. Data. Change only these two lines. ----
placebo <- c(52, 48, 55, 61, 47, 50, 58, 53, 49, 56)
treatment <- c(64, 59, 54, 66, 62, 57, 74, 60, 63, 69)
name1 <- "Placebo"; name2 <- "Treatment"
# Reading from a CSV instead (long format: a group column and a value column):
# df <- read.csv("data.csv")
# df <- df[!is.na(df$value), ]
# placebo <- df$value[df$group == "Placebo"]
# treatment <- df$value[df$group == "Treatment"]
placebo <- placebo[!is.na(placebo)] # drop missing values
treatment <- treatment[!is.na(treatment)]
n1 <- length(placebo); n2 <- length(treatment); N <- n1 + n2
# ---- 2. The test. R reports W, which is U1 for the first group. ----
fit_exact <- wilcox.test(placebo, treatment, alternative = "two.sided", exact = TRUE, correct = FALSE)
fit_norm <- wilcox.test(placebo, treatment, alternative = "two.sided", exact = FALSE, correct = TRUE)
U1 <- unname(fit_norm$statistic)
U2 <- n1 * n2 - U1
U <- min(U1, U2)
pooled <- c(placebo, treatment)
ranks <- rank(pooled)
R1 <- sum(ranks[1:n1]); R2 <- sum(ranks[(n1 + 1):N])
counts <- table(pooled)
tie_term <- sum(counts^3 - counts)
n_ties <- sum(counts[counts > 1] - 1)
mu <- n1 * n2 / 2
sigma <- sqrt(n1 * n2 / 12 * ((N + 1) - tie_term / (N * (N - 1))))
z <- (abs(U - mu) - 0.5) / sigma
use_exact <- (n_ties == 0 && n1 <= 20 && n2 <= 20)
p <- if (use_exact) fit_exact$p.value else fit_norm$p.value
method <- if (use_exact) "exact enumeration" else "normal approximation"
# ---- 3. Effect sizes and the location shift ----
r_rb <- 1 - 2 * U / (n1 * n2)
r_z <- z / sqrt(N)
cles <- U1 / (n1 * n2)
diffs <- sort(as.vector(outer(placebo, treatment, "-")))
hodges_lehmann <- median(diffs)
label <- if (abs(r_rb) >= .5) "large" else if (abs(r_rb) >= .3) "medium" else if (abs(r_rb) >= .1) "small" else "negligible"
# ---- 4. Plain English verdict ----
cat("Mann Whitney U test:", name1, "vs", name2, "\n")
cat(sprintf(" n1 = %d, n2 = %d, N = %d, ties = %d\n", n1, n2, N, n_ties))
cat(sprintf(" R1 = %.1f, R2 = %.1f (check: %.0f = %.0f)\n", R1, R2, R1 + R2, N * (N + 1) / 2))
cat(sprintf(" U1 (R calls it W) = %.2f, U2 = %.2f, reported U = %.2f\n", U1, U2, U))
cat(sprintf(" z = %.4f, p = %.4f (%s)\n", -z, p, method))
cat(sprintf(" rank biserial r = %.4f (%s), r = z/sqrt(N) = %.4f\n", r_rb, label, r_z))
cat(sprintf(" common language effect size = %.4f\n", cles))
cat(sprintf(" Hodges Lehmann shift = %.2f\n", hodges_lehmann))
cat(sprintf(" medians: %s = %.2f, %s = %.2f\n", name1, median(placebo), name2, median(treatment)))
if (p < 0.05) {
cat(sprintf(" VERDICT: the two groups differ significantly (p = %.4f), effect is %s.\n", p, label))
} else {
cat(sprintf(" VERDICT: no significant difference (p = %.4f).\n", p))
}
# ---- 5. One figure, 300 dpi ----
png("mann_whitney_boxplot.png", width = 7, height = 5, units = "in", res = 300)
boxplot(list(placebo, treatment), names = c(name1, name2),
col = c("#86efac", "#93c5fd"), ylab = "Outcome value",
main = sprintf("%s vs %s: U = %.2f, p = %.4f, r = %.2f", name1, name2, U, p, r_rb))
points(jitter(rep(1, n1), amount = .08), placebo, pch = 19, col = "#334155")
points(jitter(rep(2, n2), amount = .08), treatment, pch = 19, col = "#334155")
grid(nx = NA, ny = NULL, col = "grey85")
dev.off()
cat("Figure saved to mann_whitney_boxplot.png\n")
mann_whitney_boxplot.png in your working directory.9.2 What each line does
| Line | What it does |
|---|---|
| set.seed(42) | Fixes the jitter in the figure so the plot is reproducible |
| placebo <- c(...) | The only line you normally edit. Values for group 1 |
| read.csv(...) | Commented alternative for loading a long format CSV instead |
| placebo[!is.na(placebo)] | Drops missing values before anything else touches the data |
| wilcox.test(..., exact = TRUE) | The exact p value by enumeration, valid when there are no ties |
| wilcox.test(..., correct = TRUE) | The normal approximation with the continuity correction |
| unname(fit_norm$statistic) | Pulls out W, which is U1 for the first group |
| rank(pooled) | Ranks both groups together, averaging ties automatically |
| table(pooled) | Counts repeats so the tie correction term can be built |
| sigma <- sqrt(...) | Standard deviation of U with the tie correction applied |
| 1 - 2 * U / (n1 * n2) | The rank biserial correlation, the effect size to report |
| outer(placebo, treatment, "-") | All n1 × n2 pairwise differences for the Hodges Lehmann estimate |
| png(..., res = 300) | Opens a 300 dpi device so the figure is publication quality |
| dev.off() | Closes the device and actually writes the file. Forgetting this is the classic R mistake |
9.3 What the figure shows
A box plot for each group with every raw observation drawn on top with a small horizontal jitter. The heavy line inside each box is the median, which is what the Mann Whitney U test is about, and the box spans the interquartile range. Plotting the points as well as the box is deliberate: with ten per group a box plot alone hides how few observations there are, and a reader deserves to see that. The title carries U, the p value and the effect size, so the figure stands alone in a slide deck.
9.4 Problems and fixes
| Message or symptom | Cause | Fix |
|---|---|---|
cannot compute exact p-value with ties | Repeated values make the enumeration invalid | Not an error. Set exact = FALSE and report the normal approximation |
cannot compute exact p-value with zeroes | You ran the paired version by mistake | Make sure paired = FALSE, which is the default |
| W does not match the U you expected | R reports U1 for the first argument, not min(U1, U2) | Compute min(W, n1 * n2 - W) as the script does |
| p value differs slightly from SPSS | SPSS applies the continuity correction, R does not unless asked | Use correct = TRUE to match SPSS |
not enough 'x' observations | A group is empty after dropping missing values | Check the filter and the group label spelling |
| The PNG file is empty or missing | dev.off() was never reached | Run the whole block, and call dev.off() once for every png() |
| Formula interface gives a different answer | The factor levels are in a different order | wilcox.test(value ~ group, data = df) uses the first factor level as group 1 |
9.5 One liners worth remembering
| Task | Code |
|---|---|
| The test, two vectors | wilcox.test(x, y) |
| The test, formula interface | wilcox.test(value ~ group, data = df) |
| Exact p value | wilcox.test(x, y, exact = TRUE, correct = FALSE) |
| Match SPSS exactly | wilcox.test(x, y, exact = FALSE, correct = TRUE) |
| One tailed test | wilcox.test(x, y, alternative = "greater") |
| Hodges Lehmann shift and CI | wilcox.test(x, y, conf.int = TRUE)$estimate |
| Rank biserial effect size | 1 - 2 * U / (length(x) * length(y)) |
| Mean ranks, the SPSS style output | tapply(rank(c(x, y)), rep(1:2, c(length(x), length(y))), mean) |
| Package version with an effect size | rstatix::wilcox_effsize(df, value ~ group) |
📈 10. How to Do a Mann Whitney U Test in Python
Python does this through scipy.stats.mannwhitneyu. The important detail people miss is that SciPy returns U for the first argument, so it gives you U1, not the smaller U that textbooks report. The script below converts it for you and computes everything else.
Install with pip install numpy scipy matplotlib pandas. SciPy 1.7 or later is needed for the method="exact" argument.
10.1 The complete script
Python · runs top to bottom, change only the two data lines
# Mann Whitney U test in Python
# Requires: pip install numpy scipy matplotlib
import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from scipy.stats import mannwhitneyu, rankdata
np.random.seed(42)
# ---- 1. Data. Change only these two lines. ----
placebo = np.array([52, 48, 55, 61, 47, 50, 58, 53, 49, 56], dtype=float)
treatment = np.array([64, 59, 54, 66, 62, 57, 74, 60, 63, 69], dtype=float)
name1, name2 = "Placebo", "Treatment"
# Reading from a CSV instead (long format: one column of groups, one of values):
# import pandas as pd
# df = pd.read_csv("data.csv").dropna(subset=["value"])
# placebo = df.loc[df["group"] == "Placebo", "value"].to_numpy(dtype=float)
# treatment = df.loc[df["group"] == "Treatment", "value"].to_numpy(dtype=float)
placebo = placebo[~np.isnan(placebo)] # drop missing values
treatment = treatment[~np.isnan(treatment)]
n1, n2 = len(placebo), len(treatment)
N = n1 + n2
# ---- 2. The test. SciPy returns U for the FIRST argument, so this is U1. ----
res_exact = mannwhitneyu(placebo, treatment, alternative="two-sided", method="exact")
res_norm = mannwhitneyu(placebo, treatment, alternative="two-sided", method="asymptotic")
U1 = res_norm.statistic
U2 = n1 * n2 - U1
U = min(U1, U2)
pooled = np.concatenate([placebo, treatment])
ranks = rankdata(pooled)
R1, R2 = ranks[:n1].sum(), ranks[n1:].sum()
_, counts = np.unique(pooled, return_counts=True)
tie_term = sum(int(c) ** 3 - int(c) for c in counts)
n_ties = int(sum(c - 1 for c in counts if c > 1))
mu = n1 * n2 / 2
sigma = np.sqrt(n1 * n2 / 12 * ((N + 1) - tie_term / (N * (N - 1))))
z = (abs(U - mu) - 0.5) / sigma
p = res_exact.pvalue if (n_ties == 0 and n1 <= 20 and n2 <= 20) else res_norm.pvalue
method = "exact enumeration" if (n_ties == 0 and n1 <= 20 and n2 <= 20) else "normal approximation"
# ---- 3. Effect sizes and the location shift ----
r_rb = 1 - 2 * U / (n1 * n2)
r_z = z / np.sqrt(N)
cles = U1 / (n1 * n2)
diffs = np.sort(np.subtract.outer(placebo, treatment).ravel())
hodges_lehmann = float(np.median(diffs))
# ---- 4. Plain English verdict ----
label = "large" if abs(r_rb) >= .5 else "medium" if abs(r_rb) >= .3 else "small" if abs(r_rb) >= .1 else "negligible"
print("Mann Whitney U test:", name1, "vs", name2)
print(f" n1 = {n1}, n2 = {n2}, N = {N}, ties = {n_ties}")
print(f" R1 = {R1:.1f}, R2 = {R2:.1f} (check: {R1 + R2:.0f} = {N * (N + 1) / 2:.0f})")
print(f" U1 = {U1:.2f}, U2 = {U2:.2f}, reported U = {U:.2f}")
print(f" z = {-z:.4f}, p = {p:.4f} ({method})")
print(f" rank biserial r = {r_rb:.4f} ({label}), r = z/sqrt(N) = {r_z:.4f}")
print(f" common language effect size = {cles:.4f}")
print(f" Hodges Lehmann shift = {hodges_lehmann:.2f}")
print(f" medians: {name1} = {np.median(placebo):.2f}, {name2} = {np.median(treatment):.2f}")
if p < 0.05:
print(f" VERDICT: the two groups differ significantly (p = {p:.4f}), effect is {label}.")
else:
print(f" VERDICT: no significant difference (p = {p:.4f}).")
# ---- 5. One figure, 300 dpi ----
fig, ax = plt.subplots(figsize=(7, 5))
bp = ax.boxplot([placebo, treatment], widths=.55,
patch_artist=True, medianprops=dict(color="black", linewidth=2))
ax.set_xticks([1, 2])
ax.set_xticklabels([name1, name2])
for patch, colour in zip(bp["boxes"], ["#86efac", "#93c5fd"]):
patch.set_facecolor(colour)
for i, group in enumerate([placebo, treatment], start=1):
jitter = np.random.uniform(-.08, .08, len(group))
ax.plot(i + jitter, group, "o", color="#334155", alpha=.75, markersize=5)
ax.set_ylabel("Outcome value")
ax.set_title(f"{name1} vs {name2}: U = {U:.2f}, p = {p:.4f}, r = {r_rb:.2f}")
ax.grid(axis="y", alpha=.3)
fig.tight_layout()
fig.savefig("mann_whitney_boxplot.png", dpi=300)
print("Figure saved to mann_whitney_boxplot.png")
mann_whitney_boxplot.png.10.2 What each line does
| Line | What it does |
|---|---|
| matplotlib.use("Agg") | Draws to a file without needing a screen, so the script runs on a server |
| np.random.seed(42) | Fixes the jitter so the figure is reproducible |
| placebo = np.array([...]) | The only line you normally edit |
| pd.read_csv(...) | Commented alternative for a long format CSV |
| placebo[~np.isnan(placebo)] | Drops missing values before the test sees them |
| method="exact" | Full enumeration of the U distribution, valid only without ties |
| method="asymptotic" | The normal approximation, with the continuity correction on by default |
| res_norm.statistic | SciPy returns U1 for the first argument, so this is U1 not U |
| rankdata(pooled) | Ranks both groups together and averages ties |
| np.unique(..., return_counts=True) | Counts repeats to build the tie correction |
| np.subtract.outer(...) | All n1 × n2 pairwise differences in one vectorised call |
| 1 - 2 * U / (n1 * n2) | The rank biserial correlation |
| fig.savefig(..., dpi=300) | Writes the publication quality figure |
10.3 What the figure shows
The same box plot as the R script, drawn with matplotlib: one box per group, the median as a heavy black line, and every raw observation jittered on top so the sample size is visible. The title carries U, p and the rank biserial effect size, which makes the image usable on its own in a poster or a slide.
10.4 Problems and fixes
| Message or symptom | Cause | Fix |
|---|---|---|
| Your U does not match SPSS | SciPy returned U1, SPSS reports min(U1, U2) | Compute min(U1, n1 * n2 - U1) as the script does |
ValueError: method 'exact' not supported | Ties are present, or SciPy is older than 1.7 | Use method="asymptotic", or upgrade SciPy |
| p value differs from R | R defaults to the exact test, SciPy defaults to automatic | Set method explicitly on both sides |
nan in the output | Missing values reached the test | Filter with ~np.isnan(x) or dropna() first |
| The figure never appears | The Agg backend writes to a file, it does not open a window | Open the saved PNG, or drop the use("Agg") line locally |
alternative gives a surprising direction | "greater" means the first argument tends to be larger | Check which array you passed first |
10.5 One liners worth remembering
| Task | Code |
|---|---|
| The test | mannwhitneyu(x, y, alternative="two-sided") |
| Exact p value | mannwhitneyu(x, y, method="exact") |
| No continuity correction | mannwhitneyu(x, y, use_continuity=False) |
| One tailed test | mannwhitneyu(x, y, alternative="greater") |
| Ranks of the pooled sample | rankdata(np.concatenate([x, y])) |
| Rank biserial effect size | 1 - 2 * U / (len(x) * len(y)) |
| Hodges Lehmann shift | np.median(np.subtract.outer(x, y)) |
| Straight from a DataFrame | mannwhitneyu(df.loc[df.g=="A","v"], df.loc[df.g=="B","v"]) |
| With pingouin, effect size included | pingouin.mwu(x, y) |
📋 11. Reference Tables
Six lookup tables. The critical values below were generated by full enumeration of the U distribution, so they match the published Mann Whitney tables exactly.
Table 1. Critical values of U, two tailed test at alpha = .05
| n₁ \ n₂ | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 3 | – | – | 0 | 1 | 1 | 2 | 2 | 3 | 3 | 4 | 4 | 5 | 5 |
| 4 | – | 0 | 1 | 2 | 3 | 4 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 5 | 0 | 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 14 |
| 6 | 1 | 2 | 3 | 5 | 6 | 8 | 10 | 11 | 13 | 14 | 16 | 17 | 19 |
| 7 | 1 | 3 | 5 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 |
| 8 | 2 | 4 | 6 | 8 | 10 | 13 | 15 | 17 | 19 | 22 | 24 | 26 | 29 |
| 9 | 2 | 4 | 7 | 10 | 12 | 15 | 17 | 20 | 23 | 26 | 28 | 31 | 34 |
| 10 | 3 | 5 | 8 | 11 | 14 | 17 | 20 | 23 | 26 | 29 | 33 | 36 | 39 |
| 11 | 3 | 6 | 9 | 13 | 16 | 19 | 23 | 26 | 30 | 33 | 37 | 40 | 44 |
| 12 | 4 | 7 | 11 | 14 | 18 | 22 | 26 | 29 | 33 | 37 | 41 | 45 | 49 |
| 13 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | 33 | 37 | 41 | 45 | 50 | 54 |
| 14 | 5 | 9 | 13 | 17 | 22 | 26 | 31 | 36 | 40 | 45 | 50 | 55 | 59 |
| 15 | 5 | 10 | 14 | 19 | 24 | 29 | 34 | 39 | 44 | 49 | 54 | 59 | 64 |
What to conclude: reject the null hypothesis when your calculated U is less than or equal to the tabled value. This is the opposite direction to most tests, where you need a statistic larger than the critical value. A dash means no result can reach significance at this alpha with samples that small.
Table 2. Critical values of U, two tailed test at alpha = .01
| n₁ \ n₂ | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 3 | – | – | – | – | – | – | 0 | 0 | 0 | 1 | 1 | 1 | 2 |
| 4 | – | – | – | 0 | 0 | 1 | 1 | 2 | 2 | 3 | 3 | 4 | 5 |
| 5 | – | – | 0 | 1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 7 | 8 |
| 6 | – | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | 12 |
| 7 | – | 0 | 1 | 3 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 15 | 16 |
| 8 | – | 1 | 2 | 4 | 6 | 7 | 9 | 11 | 13 | 15 | 17 | 18 | 20 |
| 9 | 0 | 1 | 3 | 5 | 7 | 9 | 11 | 13 | 16 | 18 | 20 | 22 | 24 |
| 10 | 0 | 2 | 4 | 6 | 9 | 11 | 13 | 16 | 18 | 21 | 24 | 26 | 29 |
| 11 | 0 | 2 | 5 | 7 | 10 | 13 | 16 | 18 | 21 | 24 | 27 | 30 | 33 |
| 12 | 1 | 3 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 31 | 34 | 37 |
| 13 | 1 | 3 | 7 | 10 | 13 | 17 | 20 | 24 | 27 | 31 | 34 | 38 | 42 |
| 14 | 1 | 4 | 7 | 11 | 15 | 18 | 22 | 26 | 30 | 34 | 38 | 42 | 46 |
| 15 | 2 | 5 | 8 | 12 | 16 | 20 | 24 | 29 | 33 | 37 | 42 | 46 | 51 |
What to conclude: the same rule, reject when U is at or below the tabled value. Notice how many cells are dashes: with fewer than about five per group you cannot reach the .01 level no matter how cleanly the groups separate.
Table 3. Critical values of U, one tailed test at alpha = .05
| n₁ \ n₂ | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 3 | 0 | 0 | 1 | 2 | 2 | 3 | 4 | 4 | 5 | 5 | 6 | 7 | 7 |
| 4 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 5 | 1 | 2 | 4 | 5 | 6 | 8 | 9 | 11 | 12 | 13 | 15 | 16 | 18 |
| 6 | 2 | 3 | 5 | 7 | 8 | 10 | 12 | 14 | 16 | 17 | 19 | 21 | 23 |
| 7 | 2 | 4 | 6 | 8 | 11 | 13 | 15 | 17 | 19 | 21 | 24 | 26 | 28 |
| 8 | 3 | 5 | 8 | 10 | 13 | 15 | 18 | 20 | 23 | 26 | 28 | 31 | 33 |
| 9 | 4 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 | 33 | 36 | 39 |
| 10 | 4 | 7 | 11 | 14 | 17 | 20 | 24 | 27 | 31 | 34 | 37 | 41 | 44 |
| 11 | 5 | 8 | 12 | 16 | 19 | 23 | 27 | 31 | 34 | 38 | 42 | 46 | 50 |
| 12 | 5 | 9 | 13 | 17 | 21 | 26 | 30 | 34 | 38 | 42 | 47 | 51 | 55 |
| 13 | 6 | 10 | 15 | 19 | 24 | 28 | 33 | 37 | 42 | 47 | 51 | 56 | 61 |
| 14 | 7 | 11 | 16 | 21 | 26 | 31 | 36 | 41 | 46 | 51 | 56 | 61 | 66 |
| 15 | 7 | 12 | 18 | 23 | 28 | 33 | 39 | 44 | 50 | 55 | 61 | 66 | 72 |
What to conclude: use this table only if you predicted the direction of the difference before you collected the data. The values are larger than the two tailed table, which is exactly why a one tailed test chosen after the fact is a form of cheating.
Table 4. Effect size interpretation bands
| |r_rb| rank biserial | |r| = z / √N | Common language effect size | Label | Verdict |
|---|---|---|---|---|
| 0.00 to 0.10 | 0.00 to 0.10 | .50 to .55 | Negligible | Not worth reporting as a finding |
| 0.10 to 0.30 | 0.10 to 0.30 | .55 to .65 | Small | Real but faint |
| 0.30 to 0.50 | 0.30 to 0.50 | .65 to .75 | Medium | Clearly visible |
| 0.50 to 0.70 | 0.50 to 0.70 | .75 to .85 | Large | Strong separation |
| 0.70 and above | 0.70 and above | .85 and above | Very large | The groups barely overlap |
What to conclude: these bands come from Cohen's conventions and are a starting point, not a standard. In a field where a 2 percent improvement saves lives, a small effect can be the most important number in the paper.
Table 5. Sample size per group for 80 percent power, two tailed at alpha = .05
| Expected common language effect size | Roughly equal to r_rb | n per group (Noether) | Total N |
|---|---|---|---|
| .55 | .10 | 524 | 1048 |
| .60 | .20 | 131 | 262 |
| .65 | .30 | 59 | 118 |
| .70 | .40 | 33 | 66 |
| .75 | .50 | 21 | 42 |
| .80 | .60 | 15 | 30 |
| .85 | .70 | 11 | 22 |
| .92 | .84 | 8 | 16 |
What to conclude: read down the first column using the effect you expect from a pilot or from the literature, never from the study you have just run. Add 10 to 20 percent for dropout. These come from the Noether formula in card 7 of section 6.
Table 6. Which test should you actually be running?
| Your situation | Right test | Why |
|---|---|---|
| Two independent groups, ordinal or skewed outcome | Mann Whitney U | What this page is for |
| Two independent groups, roughly normal outcome | Independent samples t test | More power when the normality assumption holds |
| Two independent groups, very unequal variances | Welch t test or Brunner Munzel | Mann Whitney assumes similar shapes for a median reading |
| The same subjects measured twice | Wilcoxon signed rank | The observations are paired, not independent |
| Three or more independent groups | Kruskal Wallis | Running several Mann Whitney tests inflates the error rate |
| Three or more repeated measures | Friedman test | The repeated measures version of Kruskal Wallis |
| Two independent groups, binary outcome | Chi square or Fisher exact | Ranks are meaningless for a yes or no outcome |
| Ordered groups with a predicted trend | Jonckheere Terpstra | Tests the ordering directly and is more powerful |
What to conclude: the commonest error on this list is running several Mann Whitney tests across three or more groups. Use Kruskal Wallis first, then run pairwise Mann Whitney tests with a Bonferroni or Holm adjustment only if it is significant.
📈 12. Example Results
Eight worked examples covering every situation you are likely to meet, from a textbook clean result to a null result, a borderline case, heavy ties and a heavily skewed sample. Every number below was computed with the same engine that powers the calculator above.
Drug trial: systolic blood pressure
The clean case, where the test does exactly what the textbook promises.
Ten patients received a placebo and ten received the active drug. Blood pressure change was recorded after six weeks. The outcome is numeric but the sample is small, so normality cannot be checked reliably and a rank test is the safe choice.
| Statistic | Value | Note |
|---|---|---|
| Sample sizes | n₁ = 10, n₂ = 10 | Combined N = 20 |
| Rank sums | R₁ = 63.0, R₂ = 147.0 | Check total = 210 |
| Mean ranks | 6.30 vs 14.70 | Expected 10.50 under the null |
| U₁ and U₂ | 8.00 and 92.00 | They sum to n₁n₂ = 100 |
| Reported U | 8.00 | The smaller of the two |
| z score | -3.1371 | With continuity correction |
| p value, two tailed | 0.0007 | exact enumeration |
| Rank biserial r | 0.8400 | very large |
| Hodges Lehmann shift | -10.00 | Median of all pairwise differences, in mmHg |
| Medians | 52.50 vs 62.50 | Placebo versus Treatment |
| Tied observations | 0 | No ties, exact p value valid |
What it means: The two groups barely overlap. U = 8 out of a possible 100 means the placebo group lost 92 of every 100 pairwise comparisons.
How to write it: A Mann Whitney U test showed treatment values (Mdn = 62.50) were significantly higher than placebo values (Mdn = 52.50), U = 8.00, p = .001, r_rb = .84.
Reaction time after sleep deprivation
What U = 0 looks like, and why the p value still is not zero.
Eight rested and eight sleep deprived participants completed a reaction time task. Every sleep deprived participant was slower than every rested participant, so the two groups do not overlap at all.
| Statistic | Value | Note |
|---|---|---|
| Sample sizes | n₁ = 8, n₂ = 8 | Combined N = 16 |
| Rank sums | R₁ = 36.0, R₂ = 100.0 | Check total = 136 |
| Mean ranks | 4.50 vs 12.50 | Expected 8.50 under the null |
| U₁ and U₂ | 0.00 and 64.00 | They sum to n₁n₂ = 64 |
| Reported U | 0.00 | The smaller of the two |
| z score | -3.3082 | With continuity correction |
| p value, two tailed | 0.0002 | exact enumeration |
| Rank biserial r | 1.0000 | very large |
| Hodges Lehmann shift | -56.00 | Median of all pairwise differences, in milliseconds |
| Medians | 253.00 vs 309.00 | Rested versus Sleep Deprived |
| Tied observations | 0 | No ties, exact p value valid |
What it means: U = 0 is the floor. The separation cannot be any cleaner, yet with only eight per group the exact p value is .00016, not zero. Small samples limit how much certainty perfect separation can buy you.
How to write it: Reaction times were significantly slower after sleep deprivation (Mdn = 309.00 ms) than when rested (Mdn = 253.00 ms), U = 0.00, p < .001, r_rb = 1.00.
Classic textbook five versus five
A result that looks convincing on a plot and is not significant.
Five observations per group, the smallest design most textbooks use to demonstrate the test by hand. The second group is higher on every summary you could compute, and it still fails at alpha = .05.
| Statistic | Value | Note |
|---|---|---|
| Sample sizes | n₁ = 5, n₂ = 5 | Combined N = 10 |
| Rank sums | R₁ = 19.0, R₂ = 36.0 | Check total = 55 |
| Mean ranks | 3.80 vs 7.20 | Expected 5.50 under the null |
| U₁ and U₂ | 4.00 and 21.00 | They sum to n₁n₂ = 25 |
| Reported U | 4.00 | The smaller of the two |
| z score | -1.6711 | With continuity correction |
| p value, two tailed | 0.0952 | exact enumeration |
| Rank biserial r | 0.6800 | large |
| Hodges Lehmann shift | -4.00 | Median of all pairwise differences, in units |
| Medians | 14.00 vs 18.00 | Group 1 versus Group 2 |
| Tied observations | 0 | No ties, exact p value valid |
What it means: U = 4 with p = .095. The effect size of .68 is large, but with five per group there are only 252 possible rank arrangements, so no p value below .05 is even reachable unless U is 2 or less.
How to write it: The difference between the two groups was not statistically significant, U = 4.00, p = .095, r_rb = .68. The large effect size with a small sample suggests the study was underpowered rather than that no effect exists.
Two production batches, no real difference
What a genuinely null result looks like, so you can recognise one.
Ten items from each of two production batches were measured on the same quality index. The batches came off the same line on consecutive days and nothing changed in between.
| Statistic | Value | Note |
|---|---|---|
| Sample sizes | n₁ = 10, n₂ = 10 | Combined N = 20 |
| Rank sums | R₁ = 105.5, R₂ = 104.5 | Check total = 210 |
| Mean ranks | 10.55 vs 10.45 | Expected 10.50 under the null |
| U₁ and U₂ | 50.50 and 49.50 | They sum to n₁n₂ = 100 |
| Reported U | 49.50 | The smaller of the two |
| z score | -0.0000 | With continuity correction |
| p value, two tailed | 1.0000 | normal approximation |
| Rank biserial r | 0.0100 | negligible |
| Hodges Lehmann shift | 0.00 | Median of all pairwise differences, in quality index |
| Medians | 50.50 vs 50.50 | Batch A versus Batch B |
| Tied observations | 9 | Tie correction applied |
What it means: U = 49.5 against a null expectation of 50. The two groups are almost perfectly interleaved and the p value is 1.00. This is what no effect actually looks like.
How to write it: There was no significant difference between the two batches (both Mdn = 50.50), U = 49.50, p = 1.000, r_rb = .01.
Athlete VO2 max, five per group
The smallest sample that can still reach significance.
Five recreational and five elite endurance athletes had their VO2 max measured. Every elite athlete scored above every recreational athlete.
| Statistic | Value | Note |
|---|---|---|
| Sample sizes | n₁ = 5, n₂ = 5 | Combined N = 10 |
| Rank sums | R₁ = 15.0, R₂ = 40.0 | Check total = 55 |
| Mean ranks | 3.00 vs 8.00 | Expected 5.50 under the null |
| U₁ and U₂ | 0.00 and 25.00 | They sum to n₁n₂ = 25 |
| Reported U | 0.00 | The smaller of the two |
| z score | -2.5067 | With continuity correction |
| p value, two tailed | 0.0079 | exact enumeration |
| Rank biserial r | 1.0000 | very large |
| Hodges Lehmann shift | -16.00 | Median of all pairwise differences, in ml/kg/min |
| Medians | 44.00 vs 60.00 | Recreational versus Elite |
| Tied observations | 0 | No ties, exact p value valid |
What it means: U = 0 and p = .0079. Five per group is the absolute minimum for a two tailed test at alpha = .05, and only perfect separation gets you there. Add one overlapping value and significance disappears.
How to write it: Elite athletes had significantly higher VO2 max (Mdn = 60.00) than recreational athletes (Mdn = 44.00), U = 0.00, p = .008, r_rb = 1.00.
Large survey, sixty per group
Why a small p value is not the same as an important finding.
Sixty respondents in each of two conditions completed the same 0 to 150 wellbeing index. The sample is large enough that a very small shift becomes detectable.
| Statistic | Value | Note |
|---|---|---|
| Sample sizes | n₁ = 60, n₂ = 60 | Combined N = 120 |
| Rank sums | R₁ = 3106.5, R₂ = 4153.5 | Check total = 7260 |
| Mean ranks | 51.77 vs 69.22 | Expected 60.50 under the null |
| U₁ and U₂ | 1276.50 and 2323.50 | They sum to n₁n₂ = 3600 |
| Reported U | 1276.50 | The smaller of the two |
| z score | -2.7461 | With continuity correction |
| p value, two tailed | 0.0060 | normal approximation |
| Rank biserial r | 0.2908 | small |
| Hodges Lehmann shift | -8.00 | Median of all pairwise differences, in index score |
| Medians | 99.50 vs 105.50 | Condition A versus Condition B |
| Tied observations | 67 | Tie correction applied |
What it means: p = .006 looks impressive until you read the effect size of .29, which is small. The two distributions overlap heavily. With sixty per group even a six point shift on a 150 point scale reaches significance.
How to write it: Condition B scores (Mdn = 105.50) were significantly higher than Condition A scores (Mdn = 99.50), U = 1276.50, p = .006. The effect was small, r_rb = .29, so the difference is unlikely to be practically meaningful.
Ordinal satisfaction on a 1 to 7 scale
What happens when most of your values repeat.
Twelve users rated the old app and twelve rated the new one on a seven point scale. With only seven possible values and twenty four responses, ties are everywhere.
| Statistic | Value | Note |
|---|---|---|
| Sample sizes | n₁ = 12, n₂ = 12 | Combined N = 24 |
| Rank sums | R₁ = 100.0, R₂ = 200.0 | Check total = 300 |
| Mean ranks | 8.33 vs 16.67 | Expected 12.50 under the null |
| U₁ and U₂ | 22.00 and 122.00 | They sum to n₁n₂ = 144 |
| Reported U | 22.00 | The smaller of the two |
| z score | -2.9600 | With continuity correction |
| p value, two tailed | 0.0031 | normal approximation |
| Rank biserial r | 0.6944 | large |
| Hodges Lehmann shift | -1.00 | Median of all pairwise differences, in rating, 1 to 7 |
| Medians | 4.00 vs 6.00 | Old App versus New App |
| Tied observations | 19 | Tie correction applied |
What it means: Nineteen of the twenty four values are tied with something else, so the exact p value is unavailable and the tie corrected normal approximation is used instead. Without the tie correction the p value would be noticeably too large.
How to write it: New app ratings (Mdn = 6.00) were significantly higher than old app ratings (Mdn = 4.00), U = 22.00, z = -2.96, p = .003, r_rb = .69. Ties were present and the normal approximation with a tie correction was used.
Household income, rural versus urban
The case where a t test would have given the wrong answer.
Ten rural and ten urban households reported annual income in thousands. One household in each group earns far more than the rest, which is exactly what income data always looks like.
| Statistic | Value | Note |
|---|---|---|
| Sample sizes | n₁ = 10, n₂ = 10 | Combined N = 20 |
| Rank sums | R₁ = 64.0, R₂ = 146.0 | Check total = 210 |
| Mean ranks | 6.40 vs 14.60 | Expected 10.50 under the null |
| U₁ and U₂ | 9.00 and 91.00 | They sum to n₁n₂ = 100 |
| Reported U | 9.00 | The smaller of the two |
| z score | -3.0615 | With continuity correction |
| p value, two tailed | 0.0011 | exact enumeration |
| Rank biserial r | 0.8200 | very large |
| Hodges Lehmann shift | -10.50 | Median of all pairwise differences, in thousands per year |
| Medians | 21.50 vs 32.00 | Rural versus Urban |
| Tied observations | 0 | No ties, exact p value valid |
What it means: The two extreme values would dominate a t test, because a mean is pulled a long way by a single 240. Ranks flatten them: the 240 is simply the highest rank, worth no more than the second highest. U = 9 and p = .001.
How to write it: Urban household income (Mdn = 32.00) was significantly higher than rural income (Mdn = 21.50), U = 9.00, p = .001, r_rb = .82. A rank based test was used because both distributions were strongly right skewed.
🧪 13. Data Collection Protocol
Design statement: a two group between subjects design. Each unit of observation, whether that is a person, an animal, a plot or a product, is measured once and belongs to exactly one group. The outcome must be ordinal or better, meaning it can at least be ranked from lowest to highest.
- Define the unit of observation. One row of data equals one unit. If you measure five leaves on each of ten trees, the tree is the unit, not the leaf, unless you model the nesting properly.
- Define the two groups before you collect anything. Splitting a continuous variable into two groups after seeing the outcome is a well known way to manufacture a significant result.
- Assign units to groups at random wherever the design allows it. Where it does not, such as comparing two existing sites, record the variables that might confound the comparison.
- Fix the sample size in advance. Use table 5 in section 11 with an effect estimate from a pilot or from published work. Do not stop collecting the moment the p value dips below .05.
- Aim for at least 8 to 10 units per group. Below five per group a two tailed test at alpha = .05 cannot reach significance at all.
- Use one measurement scale for both groups. The same instrument, the same wording, the same number of decimal places.
- Measure blind where you can. Whoever records the outcome should not know which group the unit belongs to.
- Record the raw value, never a category. Storing 52 and 48 keeps every option open. Storing high and low throws away the ranks.
- Log missing values as blank, not as zero. A zero is a real measurement, and it will change the ranks.
- Record the date, the operator and the batch for every observation, so a systematic difference can be traced later.
- Enter the data in long format: one column for the group label, one column for the value. Every statistics package prefers it.
- Check the two group labels are spelled identically throughout. A trailing space is the single commonest data entry fault.
How the data sheet should look
| id | group | value | date | operator | notes |
|---|---|---|---|---|---|
| 001 | Placebo | 52 | 2026-03-02 | RK | |
| 002 | Placebo | 48 | 2026-03-02 | RK | |
| 011 | Treatment | 64 | 2026-03-03 | AM | reading repeated |
Minimum sample: five per group is the mathematical floor for a two tailed test at alpha = .05, and it only works with perfect separation. Ten per group is a sensible practical minimum. Twenty per group and above lets you use the normal approximation comfortably.
Pre-registration: lodge the analysis plan before you collect the data. State the alternative hypothesis, the alpha, the p value method, how ties will be handled and which effect size you will report. Template wording is in section 5, card 5.
Common mistakes in data collection
- Measuring the same subject twice and treating the two values as independent. That is a paired design and needs the Wilcoxon signed rank test.
- Rounding to whole numbers when the instrument gives decimals, which manufactures ties and throws away power.
- Collecting until the result looks good. This inflates the false positive rate badly.
- Dropping inconvenient extreme values. The whole point of a rank test is that it tolerates them.
- Recording group membership only in the file name, so the labels are lost the moment the sheets are merged.
🎯 14. When to Use the Mann Whitney U Test
- You have exactly two independent groups.
- The outcome is ordinal, such as a Likert scale, a pain score or a severity grade.
- The outcome is numeric but clearly skewed, or contains extreme values.
- The sample is small and you cannot check normality convincingly.
- You care about which group tends to score higher, rather than about means.
- Your reviewer or supervisor has asked for a non-parametric analysis.
- The same subjects were measured twice. Use the Wilcoxon signed rank test calculator.
- You have three or more groups. Use the Kruskal Wallis test calculator.
- The outcome is binary, yes or no. Use the chi square test of independence or Fisher's exact test calculator.
- The data are genuinely normal and you want maximum power. Use the independent samples t test calculator.
- The two distributions have obviously different shapes and you need a clean location comparison. Use Brunner Munzel.
- You need to adjust for covariates. Use quantile regression or an ordinal regression model.
Four situations, and what to do in each
| Situation | Decision | Why |
|---|---|---|
| Pain scores 0 to 10 for two treatment arms, 15 patients each | Mann Whitney U | Ordinal outcome, two independent groups, small sample |
| Exam marks for two class sections, 40 students each, roughly bell shaped | Independent samples t test | Normal enough, and the t test has more power |
| Number of insects on treated versus untreated plots, heavily skewed counts | Mann Whitney U, or a negative binomial model | Skewed counts, and the rank test does not assume a distribution |
| Blood pressure before and after a drug in the same 20 patients | Wilcoxon signed rank test | The measurements are paired, not independent |
A quick decision tree
- Are the two sets of measurements from the same subjects? Yes goes to Wilcoxon signed rank. No continues.
- How many groups? Three or more goes to Kruskal Wallis. Two continues.
- Is the outcome binary? Yes goes to chi square or Fisher's exact. No continues.
- Are the data roughly normal in both groups? Yes goes to the independent samples t test. No continues.
- Do the two distributions have similar shape and spread? Yes gives a clean median comparison with the Mann Whitney U test. No means you either report stochastic dominance or move to Brunner Munzel.
🔧 15. Troubleshooting and Common Errors
My U does not match the one my software reported
Cause: the three main packages report three different things. R gives W, which is U1 for the first factor level. SciPy gives U1 for the first argument. SPSS gives min(U1, U2).
Fix: this calculator prints U1, U2 and U together, so find yours in the results table and quote a matched pair of statistic and p value. Never mix R's W with a p value from another route.
My p value is slightly different from SPSS or R
Cause: either the exact versus approximate choice, or the continuity correction. R defaults to the exact test for small samples with no ties, SPSS reports the asymptotic value with a correction by default.
Fix: set the P value method dropdown deliberately rather than leaving it on Automatic, switch the continuity correction to match, and state in your methods which you used.
The calculator says the exact p value is not available
Cause: your data contain ties, or one of the groups has more than 20 values. Ties change the set of possible rank arrangements, so the enumeration no longer describes the null distribution.
Fix: nothing is wrong. The tie corrected normal approximation is the correct method here and is what every package uses in the same situation.
I get a significant result but the box plots look almost identical
Cause: a large sample makes tiny differences detectable, or the difference is in the tails rather than the middle.
Fix: read the rank biserial effect size. If it is below .10 the difference is trivial no matter how small the p value is. Report it honestly as statistically significant but practically negligible.
The two medians are identical but the test is significant
Cause: the test is not a median test. It is sensitive to the whole distribution, so two groups can share a median and still differ in how their values are spread across the ranks.
Fix: report the result as a difference in the tendency to produce larger values, quote the common language effect size, and show the distributions side by side.
A group vanished after I pasted my data
Cause: the values were separated by something the parser could not read, or a decimal comma was used where a decimal point was expected, turning 3,5 into two numbers.
Fix: use a full stop for decimals and a comma only between values. The validation message under the Run button names the exact cluster that failed.
My CSV uploaded but no columns are offered
Cause: every column was read as text, usually because of currency symbols, thousands separators or a units suffix such as mm.
Fix: strip non numeric characters in the spreadsheet first, then re-upload. Only columns with at least two numeric values are offered as clusters.
The p value came out as exactly 1
Cause: U is at or extremely close to n1 times n2 divided by 2, meaning the groups are as interleaved as they could possibly be. The doubling in the two tailed calculation is then capped at 1.
Fix: nothing to fix. This is a genuine null result, and worth reporting as one.
I ran a one tailed test and got exactly half the p value
Cause: that is the correct arithmetic when the effect runs in the predicted direction.
Fix: only use it if you fixed the direction before seeing the data. Choosing one tailed afterwards to get under .05 is a recognised research integrity problem.
More than a quarter of my values are tied
Cause: the measurement scale is too coarse for the differences you are looking for, common with 5 point scales and rounded counts.
Fix: the tie correction handles the arithmetic, but consider an ordinal regression model, or a finer measurement scale in the next study.
One group has 8 values and the other has 40
Cause: unbalanced groups, which the test handles perfectly well.
Fix: nothing needs fixing, but power is driven mostly by the smaller group. Adding more to the already large group buys you very little.
The charts did not draw
Cause: the charting library did not load, usually a blocked CDN or an offline browser.
Fix: reload the page with a working connection. Every number in the results table is computed locally and is still correct without the charts.
⚖ 16. Assumptions and Limitations
The four assumptions
| # | Assumption | How to check it | What happens if it fails |
|---|---|---|---|
| 1 | The outcome is at least ordinal | Ask whether the values can be meaningfully ranked from lowest to highest | The test is meaningless. Ranks of unordered categories carry no information. Use chi square instead |
| 2 | The two groups are independent | Confirm no unit appears in both groups and no unit is measured twice | The p value is far too small, because paired data are treated as if they carried twice the information. Use Wilcoxon signed rank |
| 3 | Observations within each group are independent | Check for clustering: siblings, repeated plots, students within a class | The p value is too small again. Use a mixed model or aggregate to the cluster level |
| 4 | Similar distribution shape, only if you want a median interpretation | Plot both groups. Compare the two interquartile ranges, as the assumption panel does automatically | The test remains valid but stops being a median comparison. It becomes a test of which group tends to produce larger values |
Limitations you should state in your write up
- Less power than a t test when the data really are normal. The efficiency is about 95 percent for normal data, so you lose a little. If the data are normal, use the t test. If they are not, this test can be far more powerful.
- It is not a median test. Without the shape assumption it tests stochastic dominance. If the shapes clearly differ, say so, or use the Brunner Munzel test.
- It cannot adjust for covariates. There is no way to control for age or baseline severity inside this test. Use quantile regression or the ordinal logistic regression calculator.
- It gives no estimate of the difference on its own. The p value tells you nothing about size, which is why this calculator adds the Hodges Lehmann shift and a confidence interval.
- It is sensitive to differences in spread as well as location. Two groups with the same centre but very different variability can produce a significant result, which is easy to misread as a difference in typical value.
- The exact p value is unavailable with ties. The approximation is good, but it is an approximation, and it should be named as such.
- Very small samples cannot reach significance at all. Below five per group, no two tailed result at alpha = .05 is possible. Reporting a non-significant result from four per group as evidence of no effect is a serious error.
- Grouping a continuous predictor to use it loses information. If your grouping variable was originally continuous, a regression model will almost always tell you more.
🏁 17. Conclusion
The Mann Whitney U test is the workhorse comparison for two independent groups when the mean is not a safe summary. By replacing values with ranks it sidesteps the normality assumption entirely, tolerates extreme values that would wreck a t test, and works on ordinal scales where averaging is not really defensible in the first place. That combination is why it appears in more published papers than almost any other non-parametric test.
Getting it right comes down to four habits. Use the exact p value when your samples are small and free of ties, because the approximation is noticeably different at that size. Always report an effect size beside the p value, since a p value alone cannot tell a reader whether the difference matters. Quote the Hodges Lehmann shift so the difference appears in units your audience understands. And be honest about the shape assumption: if the two distributions look nothing alike, you are testing which group tends to score higher, not comparing medians.
Run the analysis above to fill this conclusion with your own result. The calculator will state the verdict, the size of the effect and the shift in your original units, ready to paste into a results chapter.
❓ 18. Frequently Asked Questions
What is a Mann Whitney U test?
The Mann Whitney U test is a non-parametric test that compares two independent groups. It replaces every value with its rank in the combined sample and asks whether one group's ranks sit systematically higher than the other's. Because it works on ranks, it does not need the data to be normally distributed.
What does the Mann Whitney U test actually test?
Strictly, it tests whether a randomly chosen value from group 1 tends to be larger than a randomly chosen value from group 2. If you are willing to assume the two distributions have the same shape and spread, that becomes a test of the difference between the two medians. Without that shape assumption it is a test of stochastic dominance, not of medians.
How do I calculate the Mann Whitney U test by hand?
Rank all values from both groups together, smallest rank 1, giving tied values the average of the ranks they span. Add the ranks in group 1 to get R1. Then U1 = R1 minus n1(n1+1)/2, and U2 = n1 times n2 minus U1. The reported U is the smaller of the two. Compare it with a critical value table or convert it to a z score.
What is the formula for the Mann Whitney U test?
U1 = R1 minus n1(n1 + 1) divided by 2. U2 = n1 times n2 minus U1. The test statistic U is the smaller of U1 and U2. For large samples, z = (U minus n1 n2 / 2) divided by the standard deviation of U, which is the square root of n1 n2 (N + 1) / 12 with a tie correction applied.
When should I use the Mann Whitney U test instead of a t test?
Use it when the outcome is ordinal, when the sample is small and clearly not normal, or when the data contain extreme values that would distort a mean. If the data are roughly normal, the independent samples t test has slightly more power and is the better choice.
Is the Mann Whitney U test the same as the Wilcoxon rank sum test?
Yes. Mann and Whitney published the U form in 1947 and Wilcoxon published the rank sum form in 1945. They are algebraically the same test, so the p value is identical. R reports it as W, SPSS reports it as U, and both are correct.
What are the assumptions of the Mann Whitney U test?
Four assumptions: the outcome is at least ordinal, the two groups are independent, observations within each group are independent of each other, and, only if you want to interpret the result as a difference in medians, the two distributions have a similar shape.
Does the Mann Whitney U test assume normality?
No. That is the whole point of it. It does assume independence and, for a median interpretation, similar distribution shapes, but it never assumes the data are normally distributed.
How do I calculate the effect size for a Mann Whitney U test?
The cleanest effect size is the rank biserial correlation, r_rb = 1 minus 2U divided by (n1 times n2). It runs from minus 1 to plus 1 and can be read as the difference between the probability that a group 1 value beats a group 2 value and the probability of the reverse. This calculator reports it automatically alongside r = z divided by the square root of N.
What is a good effect size for a Mann Whitney U test?
Using the rank biserial correlation, roughly 0.10 is small, 0.30 is medium and 0.50 is large. Those are conventions, not laws. Always judge the size against what a meaningful change looks like in your own field.
How do I do a Mann Whitney U test in Excel?
Excel has no built in Mann Whitney function, so you build it: RANK.AVG to rank the pooled column, SUMIF to add the ranks per group, then arithmetic for U and NORM.S.DIST for the p value. Section 8 on this page walks through every formula with spreadsheet screenshots.
How do I do a Mann Whitney U test in R?
Use wilcox.test(values ~ group, data = df, exact = TRUE, correct = FALSE). R prints the statistic as W, which equals U1 for the first group level. Section 9 gives a complete runnable script including the effect size and a figure.
How do I do a Mann Whitney U test in Python?
Use scipy.stats.mannwhitneyu(group1, group2, alternative='two-sided'). SciPy returns U1 by default, not the smaller U, so convert if you need the classic reported value. Section 10 gives a complete script.
Why does R give me W and this calculator gives me U?
They are the same number under different labels. R's W is U for the first factor level, which is U1 here. This calculator reports the smaller of U1 and U2 as the classic U, and shows both so you can match either output.
What sample size do I need for a Mann Whitney U test?
As a working rule you need about 15 percent more participants than the equivalent t test. This calculator prints a Noether sample size estimate from your observed effect, telling you how many per group would be needed for 80 percent power. For planning a new study, use a pilot estimate rather than the result you just found.
Should I use the exact p value or the normal approximation?
Use the exact p value whenever both groups have 20 or fewer observations and there are no ties, because it is the true probability rather than an approximation. Above that, or when ties are present, the normal approximation with a tie correction is standard and very accurate.
What is the continuity correction and should I use it?
The continuity correction subtracts 0.5 from the numerator of z because a discrete statistic is being approximated by a continuous curve. It makes the p value slightly larger and slightly more conservative. Most software applies it by default and this calculator lets you switch it on or off.
How do I handle tied values in a Mann Whitney U test?
Give every tied value the average of the ranks the tie spans, then apply the tie correction to the variance of U. This calculator does both automatically and tells you how many ties it found. When ties are present the exact p value is no longer valid, so the normal approximation is used.
How do I report a Mann Whitney U test in APA style?
Report the medians, the U statistic, the sample sizes, the exact p value and an effect size. For example: a Mann Whitney U test showed that treatment scores (Mdn = 62.5) were significantly higher than placebo scores (Mdn = 52.5), U = 8.00, n1 = n2 = 10, p = .001, r_rb = .84.
What is the difference between the Mann Whitney U test and the Kruskal Wallis test?
The Mann Whitney U test compares exactly two independent groups. The Kruskal Wallis test extends the same rank logic to three or more independent groups. Running a Kruskal Wallis test on two groups gives a p value equivalent to the Mann Whitney U test.
📑 19. Cite This Tool
StatsUnlock. (2026). Mann Whitney U test calculator [Interactive statistical tool]. https://statsunlock.com/mann-whitney-u-test-calculator/@misc{statsunlock_mannwhitney_2026, title={Mann Whitney U Test Calculator}, author={{StatsUnlock}}, year={2026}, note={Interactive statistical tool}, url={https://statsunlock.com/mann-whitney-u-test-calculator/}}Differences between the two independent groups were tested with a two tailed Mann Whitney U test using the StatsUnlock Mann Whitney U Test Calculator (2026). Values were ranked across the pooled sample with tied values receiving the mean of the ranks they spanned. The exact p value was used where both group sizes were 20 or fewer and no ties were present; otherwise the normal approximation with a tie correction and a continuity correction was applied. Effect size is reported as the rank biserial correlation, and the location shift as the Hodges Lehmann estimator with a distribution free 95% confidence interval.If you also used the R or Python script from sections 9 and 10, cite the software as well: R Core Team for R, and Virtanen et al. (2020) for SciPy.
🔗 20. Related Tools
The paired version of this test. Use it when the same subjects were measured twice instead of two separate groups.
Open the tool →The same rank logic extended to three or more independent groups, so you avoid running several Mann Whitney tests.
Open the tool →The parametric counterpart. Use it when both groups are roughly normal and you want the extra power.
Open the tool →If your question is about the relationship between two ranked variables rather than a difference between two groups.
Open the tool →Convert between rank biserial, r, Cohen's d and the common language effect size, and read the interpretation bands.
Open the tool →Draw the box plot that belongs beside every Mann Whitney result, showing the medians and the overlap your reader needs to see.
Open the tool →📖 21. Glossary of Terms
| Term | Plain English meaning |
|---|---|
| Alpha | The cut off you agree on before testing, usually 0.05. If the p value falls below it you call the result significant. |
| Alternative hypothesis | The claim you are testing, for example that the two groups differ. Two tailed means either direction counts. |
| Asymptotic | A result that becomes accurate as the sample grows. The normal approximation is asymptotic. |
| Common language effect size | The chance that a value picked at random from one group beats one picked at random from the other. |
| Continuity correction | Subtracting 0.5 when a curve is used to approximate a statistic that only takes whole and half values. Makes the p value slightly larger. |
| Effect size | A number describing how big a difference is, separate from whether it is statistically detectable. |
| Exact test | A p value found by listing every possible arrangement of the ranks, rather than approximating. |
| Hodges Lehmann estimator | The median of every pairwise difference between the two groups. The shift the test is really estimating. |
| Independent groups | Two groups of different units, where no unit appears in both. |
| Interquartile range | The distance between the 25th and 75th percentile. The middle half of the data. |
| Mean rank | A group's rank sum divided by its sample size. What SPSS prints instead of U. |
| Median | The middle value once the data are sorted. Half the values sit above it. |
| Non-parametric | A method that does not assume the data follow a particular distribution such as the normal curve. |
| Null hypothesis | The starting assumption that the two groups come from the same distribution. |
| Ordinal | Data that can be ordered but where the gaps between categories are not necessarily equal, such as a 1 to 7 rating. |
| P value | The probability of a result at least this extreme if the null hypothesis were true. |
| Power | The chance of detecting a real difference of a given size. Usually targeted at 80 percent. |
| Rank | The position of a value once every value from both groups is sorted together, smallest first. |
| Rank biserial correlation | An effect size from minus 1 to plus 1, equal to the win rate minus the loss rate across all pairings. |
| Rank sum | The total of the ranks belonging to one group, written R1 or R2. |
| Skew | A distribution with a long tail on one side, so the mean is pulled away from the median. |
| Stochastic dominance | One group tending to produce larger values than the other across the whole range, not just at the centre. |
| Tie | Two or more identical values in the pooled sample. They share the average of the ranks they span. |
| U statistic | The count of pairwise wins for one group over the other, with ties counting as half a win. |
| z score | How many standard deviations the observed U sits from the value expected under the null hypothesis. |
📚 22. References
Twenty peer-reviewed journal articles, every one with a resolvable DOI link.
- Mann, H. B., & Whitney, D. R. (1947). On a test of whether one of two random variables is stochastically larger than the other. The Annals of Mathematical Statistics, 18(1), 50-60. https://doi.org/10.1214/aoms/1177730491
- Wilcoxon, F. (1945). Individual comparisons by ranking methods. Biometrics Bulletin, 1(6), 80-83. https://doi.org/10.2307/3001968
- Fay, M. P., & Proschan, M. A. (2010). Wilcoxon-Mann-Whitney or t-test? On assumptions for hypothesis tests and multiple interpretations of decision rules. Statistics Surveys, 4, 1-39. https://doi.org/10.1214/09-SS051
- Divine, G. W., Norton, H. J., Barón, A. E., & Juarez-Colunga, E. (2018). The Wilcoxon-Mann-Whitney procedure fails as a test of medians. The American Statistician, 72(3), 278-286. https://doi.org/10.1080/00031305.2017.1305291
- Hodges, J. L., & Lehmann, E. L. (1963). Estimates of location based on rank tests. The Annals of Mathematical Statistics, 34(2), 598-611. https://doi.org/10.1214/aoms/1177704172
- Lehmann, E. L. (1953). The power of rank tests. The Annals of Mathematical Statistics, 24(1), 23-43. https://doi.org/10.1214/aoms/1177729080
- Noether, G. E. (1987). Sample size determination for some common nonparametric tests. Journal of the American Statistical Association, 82(398), 645-647. https://doi.org/10.1080/01621459.1987.10478478
- Kerby, D. S. (2014). The simple difference formula: An approach to teaching nonparametric correlation. Comprehensive Psychology, 3, 11.IT.3.1. https://doi.org/10.2466/11.IT.3.1
- Brunner, E., & Munzel, U. (2000). The nonparametric Behrens-Fisher problem: Asymptotic theory and a small-sample approximation. Biometrical Journal, 42(1), 17-25. https://doi.org/10.1002/(SICI)1521-4036(200001)42:1<17::AID-BIMJ17>3.0.CO;2-U
- Bergmann, R., Ludbrook, J., & Spooren, W. P. J. M. (2000). Different outcomes of the Wilcoxon-Mann-Whitney test from different statistics packages. The American Statistician, 54(1), 72-77. https://doi.org/10.1080/00031305.2000.10474513
- Zimmerman, D. W. (1998). Invalidation of parametric and nonparametric statistical tests by concurrent violation of two assumptions. The Journal of Experimental Education, 67(1), 55-68. https://doi.org/10.1080/00220979809598344
- Vargha, A., & Delaney, H. D. (2000). A critique and improvement of the CL common language effect size statistics of McGraw and Wong. Journal of Educational and Behavioral Statistics, 25(2), 101-132. https://doi.org/10.3102/10769986025002101
- McGraw, K. O., & Wong, S. P. (1992). A common language effect size statistic. Psychological Bulletin, 111(2), 361-365. https://doi.org/10.1037/0033-2909.111.2.361
- Ruxton, G. D. (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. https://doi.org/10.1093/beheco/ark016
- Fagerland, M. W., & Sandvik, L. (2009). Performance of five two-sample location tests for skewed distributions with unequal variances. Contemporary Clinical Trials, 30(5), 490-496. https://doi.org/10.1016/j.cct.2009.06.007
- Fagerland, M. W. (2012). t-tests, non-parametric tests, and large studies: A paradox of statistical practice? BMC Medical Research Methodology, 12, 78. https://doi.org/10.1186/1471-2288-12-78
- Blair, R. C., & Higgins, J. J. (1980). A comparison of the power of Wilcoxon's rank-sum statistic to that of Student's t statistic under various nonnormal distributions. Journal of Educational Statistics, 5(4), 309-335. https://doi.org/10.3102/10769986005004309
- Newcombe, R. G. (2006). Confidence intervals for an effect size measure based on the Mann-Whitney statistic. Part 2: Asymptotic methods and evaluation. Statistics in Medicine, 25(4), 559-573. https://doi.org/10.1002/sim.2324
- Nachar, N. (2008). The Mann-Whitney U: A test for assessing whether two independent samples come from the same distribution. Tutorials in Quantitative Methods for Psychology, 4(1), 13-20. https://doi.org/10.20982/tqmp.04.1.p013
- Hart, A. (2001). Mann-Whitney test is not just a test of medians: Differences in spread can be important. BMJ, 323(7309), 391-393. https://doi.org/10.1136/bmj.323.7309.391
