Median Calculator
Paste comma-separated numbers or upload a CSV and get the median instantly, along with the quartiles, interquartile range, median absolute deviation, any percentile, a distribution-free confidence interval, and a check on whether the median or the mean is the right summary for your data.
⚡ 0. Quick Answer
The median is the middle value of a dataset once the numbers are sorted from smallest to largest.
Sort your values, then take the one in the centre. If there is an even count of values there is no single middle, so the median is the average of the two central values. Because the median depends only on position and not on magnitude, one wildly extreme value cannot move it. That robustness is why income, house prices and hospital waiting times are always reported as medians rather than means.
Rule of thumb: if the mean and median differ by more than about 10%, your data are skewed and the median is the honest summary to report.
Key takeaways
- The median is the middle value of sorted data, at position (n + 1) ÷ 2. With an even count it is the average of the two central values.
- It is robust: you could replace the largest value with a billion and the median would not move at all. Its breakdown point is 50%.
- Report it with the interquartile range, its natural spread partner, exactly as you would report a mean with a standard deviation.
- The most common error is forgetting to sort first. The median of unsorted data is meaningless.
- A median can be computed for ordinal data such as rankings and Likert scales, where a mean would not be legitimate.
📚 1. What Is the Median?
The median splits a dataset exactly in half. Sort the values, walk to the middle, and whatever value you land on is the median: half the observations lie at or below it and half lie at or above it. That definition sounds almost too simple to be useful, but it produces a property the mean can never have. Because the median is determined by where a value sits in the ordering rather than how big it is, changing the largest observation from 100 to 100 million does not shift the median by a single unit.
What this calculator reports:
- Median, the middle value, with its position shown explicitly.
- Q1 and Q3, the quartiles, which are the medians of the lower and upper halves.
- Interquartile range, Q3 minus Q1, the spread of the middle 50% and the median's natural partner.
- Median absolute deviation (MAD), the robust equivalent of the standard deviation.
- Confidence interval for the median, computed distribution-free from order statistics, which almost no other calculator provides.
- Any percentile you ask for, plus the full five number summary.
- Mean comparison, so you can see at a glance whether the data are skewed.
- Grouped median from a frequency table, for data that arrive already binned.
A worked one-liner: for the seven values 2, 4, 5, 7, 8, 9, 12 the position is (7 + 1) ÷ 2 = 4, so the median is the fourth value, 7. Add one more observation to make eight values and the position becomes 4.5, meaning you average the fourth and fifth.
Who uses it: national statistics offices report median household income because a handful of very high earners would distort the mean. Estate agents quote median house prices for the same reason. Clinicians report median survival time and median length of stay, both heavily right skewed. Ecologists use it for species counts. And anyone working with rankings or Likert scales uses it because the mean of ordinal data is not strictly meaningful.
| Measure | What it finds | Moved by one extreme value? |
|---|---|---|
| Median | The middle position | No. Breakdown point 50% |
| Mean | The balance point | Yes, arbitrarily far. Breakdown point 0% |
| Mode | The most frequent value | No, but often does not exist |
| Midrange | Halfway between min and max | Yes, extremely sensitive |
🧮 2. Set Up Your Data
Type one value per cell. Each column becomes a cluster. Empty cells are ignored.
For data that arrive already binned. Enter the lower boundary of each class and its frequency. Classes must be equal width and in ascending order.
📊 3. Results
🧠 4. Interpretation of Results, In Detail
4.1 What the median actually tells you
The median is a statement about position. It says that if you lined every observation up in order, this value would sit in the middle, with as many observations below it as above. That is all it claims, and the modesty of the claim is exactly what makes it reliable. It does not attempt to summarise the total, it does not weigh large values more heavily than small ones, and it does not assume the data have any particular shape.
The practical reading is "a typical value". When a newspaper says the median house price is 320,000, it means half the houses sold for less and half for more. If it quoted the mean instead, a single mansion changing hands could lift the figure by tens of thousands without a single ordinary house becoming more expensive. The median describes the middle of the market; the mean describes the total divided by the count, which is a different and often less useful thing.
4.2 The position formula and why an even count is different
The median sits at position (n + 1) ÷ 2 in the sorted list. With nine observations that is position 5, a whole number, so the median is an actual observed value. With ten observations it is position 5.5, which does not exist, so you take the average of the fifth and sixth values.
This has a consequence worth noticing: with an even count the median may be a number that appears nowhere in your data. The median of 2, 4, 5 and 7 is 4.5, and no one measured 4.5. That is legitimate and expected, but it occasionally confuses people who assume the median must be one of the observations. It also means that with an even number of integer values you can end up with a median ending in .5, which is fine to report as long as your measurement precision justifies it.
4.3 Why the median resists outliers and the mean does not
Statisticians describe this with the idea of a breakdown point, the proportion of the data you would have to corrupt before a statistic becomes arbitrarily wrong. The mean has a breakdown point of zero: one single value, taken far enough, drags it anywhere you like. The median has a breakdown point of 50%, the highest possible. You would have to corrupt half the dataset before you could force the median to move arbitrarily.
You can see this directly. Take the values 1, 2, 3, 4, 5. The mean and median are both 3. Now change the 5 to 500. The mean jumps to 102, while the median stays at exactly 3. The median did not merely change less, it did not change at all, because 3 is still the third of five sorted values. This is why the median is the default for income, wealth, waiting times, insurance claims and any measurement with a long tail.
4.4 The mean versus median gap, read properly
Comparing the two takes seconds and tells you the shape of your distribution. If they sit close together, the data are roughly symmetric. If the mean is above the median, there is a tail of large values pulling it up, which is right skew. If the mean is below, there is a tail of small values, which is left skew.
A gap under about 10% of the median usually means the data are symmetric enough that either summary is defensible. Between 10% and 20% you should report both. Above 20% the mean has been captured by the tail and the median is the honest choice. This calculator computes the gap and states a recommendation, but the reasoning is worth internalising because it applies to any dataset you meet.
One caution: the gap test detects skew, not every problem. Two clusters of data sitting either side of an empty middle can produce a mean and median that agree perfectly while both fall in the gap where no observation exists. The charts, not the summary statistics, are what catch that.
4.5 The interquartile range, the median's proper partner
A median on its own is as uninformative as a mean on its own. It needs a spread measure beside it, and the correct one is the interquartile range: Q3 minus Q1, the width of the middle 50% of the data. Just as you would never report a mean without a standard deviation, you should never report a median without an IQR.
The IQR shares the median's robustness. It is built from two positional values, so extreme observations cannot inflate it. This is why the standard reporting convention in medical and social research is median (IQR), sometimes written as median with the Q1 to Q3 pair in brackets. Both forms are acceptable as long as you say which you used, because "IQR = 8" and "IQR 34 to 42" convey different information at a glance.
4.6 Median absolute deviation, the robust standard deviation
The MAD is the median of the absolute distances between each value and the median. It answers "how far is a typical observation from the centre" using the same positional logic that makes the median robust in the first place.
Multiplying the MAD by the constant 1.4826 rescales it so that, for normally distributed data, it estimates the standard deviation. That constant is not arbitrary: it is the reciprocal of the 75th percentile of the standard normal distribution. The value of this is that you get an SD-like number that a single outlier cannot inflate, which makes MAD-based outlier detection considerably more reliable than the common approach of flagging anything more than three standard deviations from the mean, since a large outlier inflates the very SD being used to detect it.
4.7 The confidence interval for the median
Most calculators stop at the point estimate, but your median is computed from a sample and therefore carries uncertainty. This tool reports a confidence interval built from order statistics and the binomial distribution, which means it makes no assumption whatsoever about the shape of your data. It is exact rather than approximate, and it is valid for skewed distributions where a normal-theory interval would be wrong.
The method works by asking how many positions in from each end you must move before the probability of the true median falling outside is small enough. Because it counts whole observations, the achievable confidence levels are discrete. You cannot get exactly 95%; with sixteen observations the closest available interval is roughly 97.9%. The calculator reports the actual coverage achieved rather than pretending it hit your requested level exactly, which is the honest thing to do.
Below about six observations no 95% interval exists at all, because even the widest possible interval, from the minimum to the maximum, does not reach 95% coverage. In that case the calculator gives you the widest interval available and tells you what its true coverage is.
4.8 When the median is the wrong choice
The median is not universally superior. It discards information: it uses only the position of the middle observation and ignores everything about the magnitudes of the rest. When the data are genuinely symmetric with no outliers, the mean is more statistically efficient, meaning it varies less from sample to sample and gives you more precision for the same sample size.
The median also does not add up. Total revenue is the mean order value times the number of orders; there is no equivalent identity for the median. If your question concerns a total, or if you plan to run a t-test, ANOVA or regression, those methods are built on means and the median cannot substitute.
Finally, the median is insensitive in a way that can hide real change. If a policy improves outcomes for the worst-off quarter of a population without shifting anyone across the middle, the median will not move at all even though something important happened.
4.9 Ordinal data and why the median is often the only honest option
For ordinal data such as Likert scales, rankings and pain scores, the categories have a clear order but the gaps between them are not necessarily equal. The distance from "agree" to "strongly agree" is not guaranteed to match the distance from "neutral" to "agree". Averaging such codes assumes equal spacing that has not been established.
The median needs no such assumption. It only requires that the values can be ranked, which ordinal data satisfies by definition. This is why the median with an interquartile range is the standard summary for survey responses, and why reviewers often object to a mean Likert score.
4.10 Practical judgement
Compute both the median and the mean every time; it costs nothing. If they agree, report the mean with its standard deviation for the extra efficiency, and mention the median. If they disagree, lead with the median and its IQR, and say why. Always give n, because a median from seven observations deserves far less confidence than one from seven hundred. And plot the data before you commit to any single summary, because both the mean and the median can agree perfectly on a dataset neither of them describes.
✍ 5. How to Write Your Results in Research
▶ Run the analysis above to auto-fill all five examples with your results.
📌 Key conventions for this style
- APA abbreviates the median as Mdn, never M, which means the mean.
- Give the IQR either as a single width or as the Q1 to Q3 pair, and say which.
- Always report n so the reader can judge the stability of the estimate.
- State why you chose the median, usually skew or outliers.
📌 Key conventions for this style
- Medical journals overwhelmingly prefer median (Q1 to Q3) over median (IQR width).
- Declare the format once in the methods and keep every table row consistent.
- Report the full range separately if extreme values are clinically relevant.
- For time-to-event outcomes, state whether the median is reached at all.
📌 Key conventions for this style
- Say "a typical value" rather than "the median", and explain the half-below-half-above idea once.
- Say "the middle half" instead of "the interquartile range".
- Never use symbols such as Mdn, Q1 or IQR.
- Give units every time a number appears.
📌 Key conventions for this style
- State the method, because most readers have only seen normal-theory intervals.
- Report the actual coverage achieved, since order-statistic intervals come in discrete steps.
- Mention that no distributional assumption was made; this is a strength worth claiming.
- For small samples, note if the requested level could not be achieved.
📌 Key conventions for this style
- Give the evidence: the mean-median gap, a skewness statistic, or a figure.
- Report both values so the reader can judge for themselves.
- If outliers drove the decision, say how many and whether they were genuine.
- Do not switch silently between mean and median in different sections of the same paper.
∑ 6. Formulas Used
📝 7. How to Use This Calculator
- Enter your data. The default tab takes comma-separated numbers, exactly as the placeholder shows:
52, 48, 55, 61, 47, .... They do not need to be sorted; the calculator sorts them for you. Newlines, tabs and semicolons all work, so a column pasted from Excel is fine. - Name each cluster. The group name field above every textarea is editable. Type something meaningful such as Site A, north slope and it flows into the results table, all four charts and the exported report.
- Add or remove clusters. Press Add cluster to compare medians across groups. Every column has its own Clear and Remove button, and Remove is disabled on the last remaining column.
- Or upload a file. On the Upload tab, choose a CSV or Excel file and click the column names you want. Every column you click becomes its own cluster with its own median, quartiles and confidence interval.
- Use the Grouped Frequency tab if your data arrive already binned into classes. Enter each class's lower boundary and frequency plus the class width, and the calculator applies the interpolation formula and shows the working.
- Try a sample dataset. Ten built-in datasets cover the cases that matter: symmetric data, a single dramatic outlier, heavy income skew, an even count where the median falls between two values, ordinal Likert responses, and a bimodal set where median and mean agree but both mislead.
- Choose your quartile method. This only affects Q1 and Q3, never the median itself. Pick Tukey to match a TI-84 or a textbook, inclusive to match Excel's
QUARTILE.INCor R's default. - Set the confidence level for the median interval. Because the method counts whole observations, the achievable levels are discrete, and the calculator reports the actual coverage rather than pretending it hit your target exactly.
- Press Calculate Median. Nothing is computed until you do, and changing any input or setting clears the results so you never read stale numbers.
- Read the position box and sorted strip first. They show exactly which observation the median came from, with the middle highlighted, so you can verify the answer by eye before trusting anything else on the page.
📈 8. How to Find the Median in Excel
Excel gives you the median in one function, and unlike the mean there is no denominator convention to trip over, so MEDIAN agrees with R, Python, SPSS and this page on every dataset. What does cause trouble is everything around it: conditional medians, blanks versus zeros, and the quartile functions, which genuinely disagree with each other.
=MEDIAN(A2:A17). Add =AVERAGE(A2:A17) beneath it and you have a skew check for free.8.1 The functions you need
| You want | Excel function | Note |
|---|---|---|
| Median | =MEDIAN(A2:A17) | Ignores blanks and text. Identical across all software |
| Q1 | =QUARTILE.INC(A2:A17,1) | Interpolated. Matches R type 7 and NumPy |
| Q3 | =QUARTILE.INC(A2:A17,3) | Same method as Q1 |
| Interquartile range | =QUARTILE.INC(A2:A17,3)-QUARTILE.INC(A2:A17,1) | The median's spread partner |
| Any percentile | =PERCENTILE.INC(A2:A17,0.9) | 0.9 gives the 90th percentile |
| Median absolute deviation | =MEDIAN(ABS(A2:A17-MEDIAN(A2:A17))) | Array formula. Ctrl+Shift+Enter on older Excel |
| Conditional median | =MEDIAN(IF(B2:B50="Site A",A2:A50)) | Array formula. There is no MEDIANIF |
| Count of values | =COUNT(A2:A17) | Use COUNT, not COUNTA |
| Median position | =(COUNT(A2:A17)+1)/2 | Useful for checking by hand |
AVERAGEIF and AVERAGEIFS but no median equivalent, which surprises people constantly. Use the array form =MEDIAN(IF(condition, range)) instead. In Excel 365 it works normally; in older versions you must press Ctrl + Shift + Enter rather than Enter, and Excel will wrap it in curly braces.8.2 Step by step
1 Put your numbers in one column
Paste the values down a single column with a text label in row 1. They do not need sorting; MEDIAN sorts internally.
The 16 measurements sit in A2:A17, unsorted. Only the first eight rows are shown.
2 Median first, then mean for the skew check
=MEDIAN(A2:A17)=AVERAGE(A2:A17)Putting these two side by side turns a single number into a diagnostic. If they differ by more than about 10% of the median, your data are skewed.
Median 52.00 against a mean of 52.44, a gap of under one percent. These data are symmetric, so either summary is defensible.
3 Add the quartiles and the IQR
=QUARTILE.INC(A2:A17,1)=QUARTILE.INC(A2:A17,3)=D6-D5The finished block. Row 8 shows the form you would paste into a paper: median with the Q1 to Q3 range in brackets.
8.3 The quartile trap
The median is identical in every piece of software ever written. The quartiles are not. Excel offers two functions that disagree, and neither matches the method most textbooks teach.
| Function | Method | Matches | Q1 for our 16 leaves |
|---|---|---|---|
QUARTILE.INC | Inclusive interpolation | R type 7, NumPy, Pandas, Sheets | 49.75 |
QUARTILE.EXC | Exclusive interpolation | R type 6, Minitab | 49.25 |
| Not in Excel | Tukey, median of the lower half | TI-83/84, most textbooks | 49.50 |
The median under all three is exactly 52.00. Only Q1 and Q3 move. If your homework expects the Tukey rule, use the quartile method selector in section 2 of this page, since Excel cannot produce it directly.
8.4 Conditional medians and the blanks-versus-zeros trap
=MEDIAN(IF($B$2:$B$50="Site A",$A$2:$A$50))
This is the workaround for the missing MEDIANIF. For two conditions, nest the IF statements or multiply the conditions together:
=MEDIAN(IF(($B$2:$B$50="Site A")*($C$2:$C$50>10),$A$2:$A$50))
MEDIAN ignores empty cells entirely but treats a zero as a real observation. If missing measurements were recorded as 0, your median will be pulled down and nothing will warn you. Record missing data as blank, or filter explicitly with =MEDIAN(IF(A2:A50<>0,A2:A50)).8.5 Median in Google Sheets, SPSS and on a calculator
| Tool | How | Note |
|---|---|---|
| Google Sheets | =MEDIAN(A2:A17) | Identical to Excel. QUARTILE is the inclusive method |
| Google Sheets, conditional | =MEDIAN(FILTER(A2:A50,B2:B50="Site A")) | Cleaner than Excel's array trick |
| SPSS | Analyze → Descriptive Statistics → Frequencies → Statistics → Median | Or use Explore for median with quartiles |
| TI-83 / TI-84 | STAT → CALC → 1-Var Stats, scroll to Med | Also gives Q1 and Q3 using the Tukey rule |
| Casio scientific | Enter STAT mode, then SHIFT → 1 → MinMax | Availability varies by model |
8.6 Excel errors you will probably hit
| Excel shows | Why | Fix |
|---|---|---|
#NUM! | The range contains no numeric values | Check the range address and that numbers are not stored as text |
#VALUE! | Text or a currency symbol typed into a cell | Strip units into a separate column |
#NAME? | Function misspelled, or QUARTILE.INC on Excel 2007 | On old versions use QUARTILE |
| MEDIANIF does not exist | Excel has no such function | Use =MEDIAN(IF(condition,range)) |
| The array formula returns one wrong number | Entered with Enter rather than Ctrl+Shift+Enter | Re-enter with Ctrl+Shift+Enter on Excel 2019 and earlier |
| Median seems too low | Missing values were recorded as zeros | Blank cells are ignored; zeros are counted. Recode missing data |
| Q1 differs from a friend | One of you used INC and the other EXC | Agree on a method and state it. The median itself is unaffected |
| Median ends in .5 unexpectedly | An even count, so two middle values were averaged | Correct behaviour, not an error |
📈 9. How to Find the Median in R
R gives you the median with median(x), and unlike the mean there is no denominator convention to worry about, so the answer matches Excel, Python and SPSS exactly. The script below is a complete, copy-and-run program that computes the median, quartiles, IQR, MAD and an exact distribution-free confidence interval, then saves one publication-ready figure at 300 dpi. Base R only, nothing to install.
Rscript. Change only the x <- c(...) line.9.1 The complete script
R, base only, saves median_plot.png
# ============================================================
# Median, quartiles and IQR with a single publication-ready plot
# StatsUnlock - https://statsunlock.com/median-calculator/
# Base R only. No packages to install.
# ============================================================
# ---- 1. Your data ------------------------------------------
# Replace with your own values, or read a CSV:
# x <- read.csv("data.csv")$column_name
# x <- x[!is.na(x)]
x <- c(52, 48, 55, 61, 47, 50, 58, 53,
49, 56, 51, 54, 46, 57, 50, 52)
label <- "Site A - north slope"
units <- "mm"
# ---- 2. Median, quartiles, MAD -----------------------------
xs <- sort(x) # sorting first is essential
n <- length(xs)
med <- median(xs)
qs <- quantile(xs, c(0.25, 0.75), type = 7) # type 7 = Excel INC
q1 <- as.numeric(qs[1]); q3 <- as.numeric(qs[2])
iqr <- q3 - q1
# CAREFUL: R's mad() multiplies by 1.4826 by default.
mad_raw <- mad(xs, constant = 1) # the plain median absolute deviation
mad_sd <- mad(xs) # already scaled to estimate the SD
mean_x <- mean(xs)
gap <- abs(mean_x - med) / med * 100
lo_fence <- q1 - 1.5 * iqr
hi_fence <- q3 + 1.5 * iqr
outliers <- xs[xs < lo_fence | xs > hi_fence]
# ---- 3. Distribution-free CI for the median ----------------
# Exact, from binomial order statistics. No normality assumed.
median_ci <- function(v, conf = 0.95) {
v <- sort(v); m <- length(v); alpha <- 1 - conf
cum <- 0; k <- 0
for (i in 0:m) {
p <- dbinom(i, m, 0.5)
if (cum + p > alpha / 2) break
cum <- cum + p; k <- i + 1
}
exact <- TRUE
if (k < 1) { k <- 1; cum <- dbinom(0, m, 0.5); exact <- FALSE }
list(lo = v[k], hi = v[m - k + 1], coverage = 1 - 2 * cum, exact = exact)
}
ci <- median_ci(xs, 0.95)
cat(sprintf("n = %d\n", n))
cat(sprintf("position = (n+1)/2 = %.1f\n", (n + 1) / 2))
cat(sprintf("median = %.4f\n", med))
cat(sprintf("Q1, Q3 = %.4f, %.4f IQR = %.4f\n", q1, q3, iqr))
cat(sprintf("MAD = %.4f (scaled -> %.4f)\n", mad_raw, mad_sd))
cat(sprintf("mean = %.4f gap = %.1f%%\n", mean_x, gap))
cat(sprintf("%s CI = [%.4f, %.4f] actual coverage %.4f\n",
if (ci$exact) "95%" else "widest", ci$lo, ci$hi, ci$coverage))
cat(sprintf("verdict : %s\n",
if (gap < 10) "symmetric, mean is fine too" else "skewed, report the median"))
# ---- 4. One figure, two stacked panels ---------------------
png("median_plot.png", width = 2700, height = 1800, res = 300)
layout(matrix(c(1, 2), nrow = 2), heights = c(1.5, 1))
par(mar = c(0.6, 5, 5, 2), family = "sans")
xr <- range(pretty(xs))
# upper panel: horizontal box plot
boxplot(xs, horizontal = TRUE, ylim = xr, axes = FALSE,
col = "#e9d5ff", border = "#9333ea", lwd = 2,
medlwd = 4, outpch = 21, outbg = "#fff7ed", outcol = "#c2410c",
outcex = 1.3, boxwex = 0.55)
# CI band for the median, drawn behind by re-plotting the box on top
rect(ci$lo, 0.55, ci$hi, 1.45,
col = adjustcolor("#9333ea", alpha.f = 0.10), border = NA)
boxplot(xs, horizontal = TRUE, add = TRUE, axes = FALSE,
col = adjustcolor("#e9d5ff", alpha.f = 0.85), border = "#9333ea",
lwd = 2, medlwd = 4, outpch = 21, outbg = "#fff7ed",
outcol = "#c2410c", outcex = 1.3, boxwex = 0.55)
abline(v = mean_x, col = "#c2410c", lwd = 2.4, lty = 2)
title(main = sprintf("%s: median, quartiles and spread", label),
adj = 0, cex.main = 1.15, font.main = 2, line = 3)
title(main = sprintf("n = %d median = %.2f %s IQR = %.2f Q1 = %.2f Q3 = %.2f",
n, med, units, iqr, q1, q3),
adj = 0, cex.main = 0.95, font.main = 1, line = 1.6)
legend("topright", bty = "n", cex = 0.92,
lwd = c(8, 2.4, 4), lty = c(1, 2, 1),
col = c(adjustcolor("#9333ea", alpha.f = 0.15), "#c2410c", "#581c87"),
legend = c(sprintf("%.1f%% CI for the median", ci$coverage * 100),
sprintf("Mean = %.2f", mean_x),
sprintf("Median = %.2f", med)))
# lower panel: every raw value, jittered so ties are visible
par(mar = c(4.6, 5, 0.6, 2))
set.seed(42) # seed = reproducible jitter
is_out <- xs %in% outliers
plot(xs, runif(n, -0.3, 0.3), xlim = xr, ylim = c(-1, 1),
yaxt = "n", bty = "n", xlab = sprintf("Value (%s)", units), ylab = "",
pch = 21, cex = 1.5, cex.lab = 1.05,
bg = ifelse(is_out, "#fff7ed", adjustcolor("#9333ea", alpha.f = 0.7)),
col = ifelse(is_out, "#c2410c", "white"), lwd = ifelse(is_out, 2, 1.1))
mtext("Raw\ndata", side = 2, line = 1.6, las = 1, cex = 0.8)
abline(v = med, col = "#581c87", lwd = 2.6)
abline(v = c(q1, q3), col = "#2563eb", lwd = 1.7, lty = 3)
dev.off()
cat("\nSaved median_plot.png\n")
Run it with Rscript median_plot.R, or paste it into the RStudio console. The figure appears as median_plot.png in your working directory, which getwd() will tell you.
mad(x) does not return the median absolute deviation. By default R multiplies it by 1.4826 to make it an estimate of the standard deviation. If you want the plain MAD you must write mad(x, constant = 1). This catches almost everyone the first time, and it is the median-world equivalent of Python's ddof trap.9.2 What each part does
| Line or function | What it does, and why it is there |
|---|---|
| x <- c(...) | Builds the numeric vector. Swap in read.csv("data.csv")$col for a real file, and drop missing values with x[!is.na(x)] so you know the true n. |
| sort(x) | Sorts ascending. median() sorts internally anyway, but having the sorted vector lets the confidence interval index directly into order statistics. |
| median(xs) | The median. With NA present use median(x, na.rm = TRUE), but check how many values that silently removed. |
| quantile(xs, type = 7) | The quartiles. R offers nine quantile types; type 7 is the default and matches Excel's QUARTILE.INC and NumPy. Use type = 6 to match QUARTILE.EXC, or type = 2 for something close to the textbook Tukey rule. |
| as.numeric(qs[1]) | Strips the names from the quantile result. Without this, sprintf would print the "25%" label alongside the number. |
| mad(xs, constant = 1) | The raw median absolute deviation. The constant = 1 is essential, since R defaults to 1.4826. |
| mad(xs) | The scaled version, which estimates the standard deviation for roughly normal data and resists outliers in a way the actual SD cannot. |
| gap | Percentage difference between mean and median, the fastest skew detector available. |
| dbinom(i, m, 0.5) | The binomial probability used to build the confidence interval. Under the null, each observation is equally likely to fall above or below the true median, which is what makes this interval assumption-free. |
| median_ci() | Walks in from each end until the tail probability exceeds alpha/2, then returns those two order statistics as the interval bounds along with the coverage actually achieved. |
| exact flag | Below about n = 6 no 95% interval exists at all. The function then returns the widest available interval and flags that the requested level was not reached, rather than quietly reporting something false. |
| png(..., res = 300) | Opens a file graphics device at print resolution. Without res you get a blurry 72 dpi image that journals reject. |
| layout(matrix(c(1,2))) | Stacks two panels with heights = c(1.5, 1) so the box plot gets more room than the raw-data strip. |
| boxplot(horizontal = TRUE) | Draws the box plot sideways so it shares an x-axis with the panel beneath. boxwex controls the box thickness. |
| rect() then boxplot(add = TRUE) | Base R has no z-order, so the CI band is drawn first and the box is redrawn on top of it. This is the standard base-graphics workaround for layering. |
| adjustcolor(alpha.f) | Adds transparency. alpha.f = 0.10 is 10% opaque, enough to tint without hiding what is underneath. |
| xs %in% outliers | A logical vector marking which points are outliers, used by ifelse() to colour them differently in the lower panel. |
| set.seed(42) | Fixes the jitter so the figure is reproducible. Never publish a figure containing unseeded randomness. |
| dev.off() | Closes the device and finalises the PNG. Forgetting this leaves a zero-byte or locked file, the most common R plotting error. |
9.3 What the figure shows
The upper panel is a horizontal box plot: the box spans Q1 to Q3, the thick line inside is the median, the whiskers reach the furthest values within 1.5 times the IQR, and anything beyond appears as an individual point. Behind the box sits a shaded band showing the confidence interval for the median, and a dashed orange line marks the mean so you can see at a glance whether it has been pulled away by skew.
The lower panel plots every observation with a small vertical jitter, sharing the x-axis, with outliers picked out in orange and dotted blue lines at the quartiles. The box plot tells you the summary; the strip tells you the truth, including ties, gaps and clumping that binning would hide.
9.4 Common R problems and fixes
| Symptom | Cause | Fix |
|---|---|---|
mad(x) is bigger than expected | R scaled it by 1.4826 by default | Use mad(x, constant = 1) for the plain MAD |
median(x) returns NA | The vector contains a missing value | median(x, na.rm = TRUE), or clean first so you know the real n |
| Quartiles differ from Excel | Different quantile type | type = 7 matches QUARTILE.INC; type = 6 matches QUARTILE.EXC |
| Quantile output has "25%" labels | Named vector returned | Wrap with as.numeric() or use unname() |
| The PNG is empty | dev.off() never called | Always close the device; while (dev.cur() > 1) dev.off() if stuck |
| The CI band hides the box | Drawn after the box plot | Draw the rectangle first, then redraw the box with add = TRUE |
| Only one panel appears | layout() reset by a later par() | Call layout() once, right after opening the device |
| Box plot is vertical | Default orientation | Pass horizontal = TRUE |
9.5 Useful one-liners
| You want | R code |
|---|---|
| Median | median(x) |
| Five number summary | fivenum(x) or summary(x) |
| Quartiles | quantile(x, c(0.25, 0.75)) |
| Interquartile range | IQR(x) |
| Any percentile | quantile(x, 0.90) |
| Plain MAD | mad(x, constant = 1) |
| Robust SD estimate | mad(x) |
| Median by group | tapply(df$value, df$group, median) |
| Test the median against a value | wilcox.test(x, mu = 50) |
| CI for the median, package version | DescTools::MedianCI(x) |
📈 10. How to Find the Median in Python
Python's np.median(x) matches every other tool exactly, which makes the median far less error-prone than the mean and its ddof trap. The script below is complete and runnable: it computes the median, quartiles, IQR, MAD and an exact distribution-free confidence interval, then saves one 300 dpi figure ready for a paper or a slide.
math.comb from the standard library. Change only the x = np.array([...]) line.Install with pip install numpy matplotlib if you do not already have them. No SciPy required.
10.1 The complete script
Python 3, saves median_plot.png
# ============================================================
# Median, quartiles and IQR with a single publication-ready plot
# StatsUnlock - https://statsunlock.com/median-calculator/
# ============================================================
import numpy as np
import matplotlib.pyplot as plt
from math import comb
# ---- 1. Your data ------------------------------------------
# Replace with your own values, or read a CSV:
# import pandas as pd
# x = pd.read_csv("data.csv")["column_name"].dropna().to_numpy()
x = np.array([52, 48, 55, 61, 47, 50, 58, 53,
49, 56, 51, 54, 46, 57, 50, 52], dtype=float)
label = "Site A - north slope"
units = "mm"
# ---- 2. Median, quartiles, MAD -----------------------------
xs = np.sort(x) # sorting first is essential
n = xs.size
median = np.median(xs)
q1, q3 = np.percentile(xs, [25, 75])
iqr = q3 - q1
mad = np.median(np.abs(xs - median))
mad_sd = 1.4826 * mad # robust estimate of the SD
mean_x = np.mean(xs)
gap = abs(mean_x - median) / median * 100
lo_fence, hi_fence = q1 - 1.5 * iqr, q3 + 1.5 * iqr
outliers = xs[(xs < lo_fence) | (xs > hi_fence)]
inliers = xs[(xs >= lo_fence) & (xs <= hi_fence)]
# ---- 3. Distribution-free CI for the median ----------------
# Exact, from binomial order statistics. No normality assumed.
def median_ci(sorted_x, conf=0.95):
m = sorted_x.size
alpha = 1 - conf
cum, k = 0.0, 0
for i in range(m + 1):
p = comb(m, i) / 2 ** m
if cum + p > alpha / 2:
break
cum += p
k = i + 1
exact = True
if k < 1: # sample too small for this level
k, cum, exact = 1, comb(m, 0) / 2 ** m, False
return sorted_x[k - 1], sorted_x[m - k], 1 - 2 * cum, exact
ci_lo, ci_hi, coverage, exact = median_ci(xs, 0.95)
print(f"n = {n}")
print(f"position = (n+1)/2 = {(n + 1) / 2}")
print(f"median = {median:.4f}")
print(f"Q1, Q3 = {q1:.4f}, {q3:.4f} IQR = {iqr:.4f}")
print(f"MAD = {mad:.4f} (x1.4826 -> {mad_sd:.4f})")
print(f"mean = {mean_x:.4f} gap = {gap:.1f}%")
print(f"{'95%' if exact else 'widest'} CI = [{ci_lo:.4f}, {ci_hi:.4f}]"
f" actual coverage {coverage:.4f}")
print("verdict :",
"symmetric, mean is fine too" if gap < 10 else "skewed, report the median")
# ---- 4. One figure, two stacked panels ---------------------
fig, (ax_box, ax_dot) = plt.subplots(
2, 1, figsize=(9, 6.0), sharex=True,
gridspec_kw={"height_ratios": [1.5, 1], "hspace": 0.12})
bp = ax_box.boxplot(xs, vert=False, widths=0.55, patch_artist=True,
whis=1.5, showfliers=True,
boxprops=dict(facecolor="#e9d5ff", edgecolor="#9333ea", lw=2),
medianprops=dict(color="#581c87", lw=3),
whiskerprops=dict(color="#9333ea", lw=1.8),
capprops=dict(color="#9333ea", lw=1.8),
flierprops=dict(marker="o", markerfacecolor="#fff7ed",
markeredgecolor="#c2410c", markersize=8,
markeredgewidth=1.8))
ax_box.axvspan(ci_lo, ci_hi, color="#9333ea", alpha=0.10, zorder=0,
label=f"{coverage*100:.1f}% CI for the median")
ax_box.axvline(mean_x, color="#c2410c", lw=2.2, ls="--", zorder=4,
label=f"Mean = {mean_x:.2f}")
ax_box.plot([], [], color="#581c87", lw=3, label=f"Median = {median:.2f}")
ax_box.set_yticks([])
ax_box.set_title(f"{label}: median, quartiles and spread\n"
f"n = {n} median = {median:.2f} {units} "
f"IQR = {iqr:.2f} Q1 = {q1:.2f} Q3 = {q3:.2f}",
fontsize=12, fontweight="bold", loc="left")
ax_box.legend(frameon=False, fontsize=9.5, loc="upper right")
ax_box.grid(axis="x", alpha=0.25, zorder=0)
ax_box.spines[["top", "right", "left"]].set_visible(False)
rng = np.random.default_rng(42) # seed = reproducible jitter
ax_dot.scatter(inliers, rng.uniform(-0.3, 0.3, inliers.size),
s=55, color="#9333ea", alpha=0.7,
edgecolor="white", linewidth=0.9, zorder=3, label="Values")
if outliers.size:
ax_dot.scatter(outliers, rng.uniform(-0.3, 0.3, outliers.size),
s=80, facecolor="#fff7ed", edgecolor="#c2410c",
linewidth=2, zorder=4, label="Outliers")
ax_dot.axvline(median, color="#581c87", lw=2.4, zorder=2)
ax_dot.axvline(q1, color="#2563eb", lw=1.6, ls=":", zorder=2)
ax_dot.axvline(q3, color="#2563eb", lw=1.6, ls=":", zorder=2)
ax_dot.set_ylim(-1, 1)
ax_dot.set_yticks([])
ax_dot.set_xlabel(f"Value ({units})", fontsize=11)
ax_dot.set_ylabel("Raw\ndata", fontsize=9, rotation=0, ha="right", va="center")
ax_dot.grid(axis="x", alpha=0.25, zorder=0)
ax_dot.spines[["top", "right", "left"]].set_visible(False)
if outliers.size:
ax_dot.legend(frameon=False, fontsize=9, loc="upper right")
fig.savefig("median_plot.png", dpi=300, bbox_inches="tight")
print("\nSaved median_plot.png")
Run it with python median_plot.py. In Jupyter, replace the savefig line with plt.show(), or keep both to display and save at once.
10.2 What each part does
| Line or function | What it does, and why it is there |
|---|---|
| np.array([...], dtype=float) | Builds the array. Forcing float keeps the median exact when an even count makes it fall between two integers. |
| np.sort(x) | Sorts ascending. np.median sorts internally, but the confidence interval needs to index directly into order statistics. |
| np.median(xs) | The median. With NaN present this returns NaN; use np.nanmedian(x) to skip them, but check how many you skipped. |
| np.percentile(xs, [25, 75]) | Q1 and Q3 in one call. NumPy uses linear interpolation, matching Excel's QUARTILE.INC and R's type 7. Pass method="lower" or others for different conventions. |
| np.median(np.abs(xs - median)) | The median absolute deviation, computed explicitly. Note the contrast with R, where mad() silently applies the 1.4826 scaling; here you multiply yourself, so nothing is hidden. |
| 1.4826 * mad | Rescales the MAD to estimate the standard deviation for roughly normal data. The constant is the reciprocal of the 75th percentile of the standard normal. |
| boolean masking | xs[(xs < lo_fence) | (xs > hi_fence)] selects outliers in one expression. The brackets around each comparison are required because | binds tighter than < in Python. |
| comb(m, i) / 2 ** m | The binomial probability P(X = i) with p = 0.5. Using math.comb avoids a SciPy dependency entirely. |
| median_ci() | Walks in from each end until the tail probability exceeds alpha/2, then returns those order statistics as bounds. Because it counts whole observations, the achievable coverage is discrete, so the function returns what it actually achieved rather than what you asked for. |
| exact flag | Below about n = 6 no 95% interval exists. The function falls back to the widest interval available and reports that the level was not reached. |
| plt.subplots(2, 1, sharex=True) | Two stacked panels sharing an x-axis, so the median line in the box plot lines up exactly with the one below it. |
| gridspec_kw height_ratios | Gives the box plot 1.5 times the height of the raw-data strip, with hspace pulling them close together. |
| ax.boxplot(vert=False) | Horizontal box plot. patch_artist=True is required before boxprops facecolor will do anything, which catches people out. |
| whis=1.5 | The whisker rule: reach to the furthest point within 1.5 times the IQR. This is the Tukey convention and the default. |
| ax.axvspan(ci_lo, ci_hi) | Shades the confidence interval for the median behind everything else via zorder=0. |
| ax.plot([], [], ...) | Plots nothing, purely to add a legend entry for the median line, which the box plot draws but does not label. |
| rng = np.random.default_rng(42) | The modern seeded NumPy generator, so the jitter is identical on every run. |
| spines[[...]].set_visible(False) | Removes the box lines around the plot. A small change that stops the figure looking like a default Matplotlib output. |
| savefig(dpi=300, bbox_inches="tight") | Writes at print resolution and trims whitespace. Most journals require 300 dpi minimum. |
10.3 What the figure shows
The same figure the R script produces, drawn by a different engine. Upper panel: a horizontal box plot with the CI band for the median shaded behind it and the mean marked with a dashed line. Lower panel: every raw observation jittered vertically, outliers picked out, quartiles marked with dotted lines.
Showing both is deliberate. A box plot compresses your data into five numbers, which is exactly what makes it useful and exactly what makes it capable of hiding things. Two clusters with an empty middle, heavy ties, or a gap will all look unremarkable in the box and obvious in the strip beneath it.
10.4 Common Python problems and fixes
| Symptom | Cause | Fix |
|---|---|---|
Median returns nan | The array contains a NaN | Use np.nanmedian(x), or filter with x[~np.isnan(x)] |
| MAD disagrees with R | R's mad() scales by 1.4826 by default; NumPy does not | Compare like with like: R's mad(x, constant = 1) equals the raw NumPy version |
| Quartiles differ from a textbook | NumPy interpolates; textbooks often use the Tukey rule | Use the quartile selector in section 2 of this page, or method= in newer NumPy |
| Box plot has no fill colour | patch_artist=True not set | Add it before passing facecolor in boxprops |
TypeError on the outlier mask | Missing brackets around each comparison | Write (xs < a) | (xs > b), not xs < a | xs > b |
| Figure is blurry | Saved at the default 100 dpi | Pass dpi=300, or save as .pdf or .svg |
| Labels cut off | Default bounding box clips text | Use bbox_inches="tight", already included |
| Jitter changes each run | Generator not seeded | Use np.random.default_rng(42) |
| Nothing displays when run | Non-interactive backend, common on servers | The script saves to file, so this is fine. Add plt.show() to display |
10.5 Useful one-liners
| You want | Python code |
|---|---|
| Median | np.median(x) |
| Median ignoring missing values | np.nanmedian(x) |
| Everything at once | pd.Series(x).describe() |
| Quartiles | np.percentile(x, [25, 75]) |
| Interquartile range | scipy.stats.iqr(x) |
| Any percentile | np.percentile(x, 90) |
| Median absolute deviation | np.median(np.abs(x - np.median(x))) |
| Robust SD estimate | scipy.stats.median_abs_deviation(x, scale="normal") |
| Median by group | df.groupby("group")["value"].median() |
| Test the median against a value | scipy.stats.wilcoxon(x - 50) |
mad(x, constant = 1) against the raw NumPy calculation.📋 11. Reference Tables
11.1 How one value destroys the mean and leaves the median untouched
| Dataset | Mean | Median | What changed |
|---|---|---|---|
| 1, 2, 3, 4, 5 | 3.00 | 3.00 | Baseline, both agree |
| 1, 2, 3, 4, 500 | 102.00 | 3.00 | Mean up 34-fold, median unmoved |
| 1, 2, 3, 4, 5000 | 1002.00 | 3.00 | Mean up 334-fold, median still unmoved |
Conclusion: the median did not merely change less, it did not change at all. Three is still the third of five sorted values however large the fifth becomes. This is the entire argument for the median in three rows.
11.2 Odd versus even counts
| Data | n | Position (n+1)/2 | Median | Is it an observed value? |
|---|---|---|---|---|
| 2, 4, 5, 7, 8, 9, 12 | 7 | 4 | 7 | Yes, the 4th value |
| 2, 4, 5, 7, 8, 9, 12, 15 | 8 | 4.5 | 7.5 | No, the average of the 4th and 5th |
Conclusion: a fractional position means average the two values either side. With an even count the median may be a number that appears nowhere in your data, which is correct rather than an error.
11.3 Confidence interval coverage by sample size
Requesting 95%. Because the method counts whole observations, the achievable coverage is discrete and almost never exactly 95%.
| n | Interval | Actual coverage | Status |
|---|---|---|---|
| 5 | x(1) to x(5), the full range | 93.75% | Cannot reach 95% |
| 6 | x(1) to x(6) | 96.88% | Widest possible |
| 10 | x(2) to x(9) | 97.85% | Exact |
| 12 | x(3) to x(10) | 96.14% | Exact |
| 16 | x(4) to x(13) | 97.87% | Exact |
| 20 | x(6) to x(15) | 95.86% | Exact |
| 30 | x(10) to x(21) | 95.72% | Exact |
| 50 | x(18) to x(33) | 96.72% | Exact |
| 100 | x(40) to x(61) | 96.48% | Exact |
Conclusion: coverage is always at least 95% when the interval exists, so the method is conservative rather than optimistic. Below n = 6 no 95% interval is possible even using the full range, and the calculator says so rather than reporting something false.
11.4 Why MAD beats the standard deviation for outlier detection
Base data 10 to 19. In the second row the value 19 is replaced by 500.
| Data | Standard deviation | MAD | MAD × 1.4826 |
|---|---|---|---|
| 10 to 19, clean | 3.028 | 2.500 | 3.706 |
| Same, with one value changed to 500 | 153.708 | 2.500 | 3.706 |
Conclusion: the standard deviation grew fifty-fold while the MAD did not move at all. This is why flagging outliers as "more than three standard deviations from the mean" is self-defeating: the outlier inflates the very yardstick you are using to detect it. Use the median and MAD instead.
11.5 Median from grouped frequency data
Worked example using the interpolation formula, classes of width 10.
| Class | Frequency | Cumulative frequency | Contains the median? |
|---|---|---|---|
| 0 to 10 | 5 | 5 | No |
| 10 to 20 | 8 | 13 | No, 13 < 20 |
| 20 to 30 | 15 | 28 | Yes, 28 ≥ 20 |
| 30 to 40 | 7 | 35 | No |
| 40 to 50 | 5 | 40 | No |
With n = 40, we need position n/2 = 20. The cumulative frequency first reaches 20 in the class 20 to 30, so L = 20, CF = 13, f = 15 and w = 10:
Conclusion: this interpolates within the median class, assuming the values are spread evenly across it. It is an estimate, not an exact median, and it is the best you can do when the raw values have been discarded.
11.6 Which average to report
| Your data | Report | With |
|---|---|---|
| Symmetric, no outliers | Mean | Standard deviation |
| Skewed, or contains outliers | Median | Interquartile range |
| Ordinal, such as Likert scales | Median | Interquartile range |
| Mean and median differ by 10 to 20% | Both | SD and IQR, and say why |
| Two clear clusters | Neither, split the data | A summary for each group |
| You need a total, or a t-test | Mean | The median does not add up |
Conclusion: the median is not automatically better, it is better under specific conditions. When the data are clean and symmetric the mean is more efficient and should be preferred.
📈 12. Example Results
Note: every example below uses the Tukey quartile method, the calculator default. The median is identical under all three methods; only Q1, Q3 and the IQR change.
Leaf length, an even count
The clean case, and a reminder of what an even n does.
Sixteen leaves were measured to the nearest millimetre. The class wants a typical value.
| Statistic | Value | Note |
|---|---|---|
| n | 16 | Number of values |
| Position (n+1)/2 | 8.5 | Where the median sits |
| Median | 52 | The middle value |
| Mean | 52.438 | For comparison |
| Mean vs median gap | 0.8% | Skew detector |
| Q1 | 49.5 | 25th percentile |
| Q3 | 55.5 | 75th percentile |
| IQR | 6 | Q3 minus Q1 |
| MAD | 3 | Median absolute deviation |
| 97.9% CI for median | 49 to 56 | Distribution-free |
| Outliers | none | Beyond 1.5 x IQR |
What it means: With sixteen values the position is (16+1)/2 = 8.5, so the median is the average of the eighth and ninth sorted values, both 52, giving exactly 52. The mean is 52.44, a gap of under one percent, so these data are symmetric and either summary would be defensible. The confidence interval runs from 49 to 56 with 97.9% coverage.
How to write it: "Leaf length had a median of 52.0 mm (IQR 6.0, Q1 49.5, Q3 55.5, n = 16)."
One director salary
Where the mean describes nobody and the median describes everybody.
Twelve staff salaries in thousands. Eleven cluster in the thirties and forties; one director earns 180.
| Statistic | Value | Note |
|---|---|---|
| n | 12 | Number of values |
| Position (n+1)/2 | 6.5 | Where the median sits |
| Median | 38.5 | The middle value |
| Mean | 50.083 | For comparison |
| Mean vs median gap | 30.1% | Skew detector |
| Q1 | 35 | 25th percentile |
| Q3 | 43 | 75th percentile |
| IQR | 8 | Q3 minus Q1 |
| MAD | 4 | Median absolute deviation |
| 96.1% CI for median | 34 to 44 | Distribution-free |
| Outliers | 180 | Beyond 1.5 x IQR |
What it means: The mean of 50.08 sits above every ordinary salary in the room except the director's, so it describes nobody actually employed there. The median of 38.5 sits comfortably among real staff. The outlier is flagged automatically, and note that the median would be identical if the director earned 180 or 1,800.
How to write it: "Salary had a median of 38.5 thousand (IQR 8.0, n = 12); the mean of 50.1 is not reported as representative because of one extreme value."
Household income
The classic case where every statistics agency reports the median.
Fifteen household incomes in thousands, with the long right tail typical of income everywhere.
| Statistic | Value | Note |
|---|---|---|
| n | 15 | Number of values |
| Position (n+1)/2 | 8 | Where the median sits |
| Median | 42 | The middle value |
| Mean | 58.467 | For comparison |
| Mean vs median gap | 39.2% | Skew detector |
| Q1 | 31 | 25th percentile |
| Q3 | 67 | 75th percentile |
| IQR | 36 | Q3 minus Q1 |
| MAD | 13 | Median absolute deviation |
| 96.5% CI for median | 31 to 67 | Distribution-free |
| Outliers | 210 | Beyond 1.5 x IQR |
What it means: The median of 42 has eight households below and seven above. The mean of 58.47 exceeds the median by 39%, and two thirds of these households earn less than it. This is precisely why national statistics offices report median household income, and why quoting the mean would misrepresent the typical household.
How to write it: "Household income had a median of 42.0 thousand (IQR 36.0, range 22 to 210, n = 15); the distribution was strongly right skewed."
Likert survey responses
Where the median is the only strictly defensible average.
Twenty respondents rated a service from 1 to 5. The categories are ordered, but the gap from 4 to 5 is not guaranteed to equal the gap from 2 to 3.
| Statistic | Value | Note |
|---|---|---|
| n | 20 | Number of values |
| Position (n+1)/2 | 10.5 | Where the median sits |
| Median | 4 | The middle value |
| Mean | 4 | For comparison |
| Mean vs median gap | 0% | Skew detector |
| Q1 | 4 | 25th percentile |
| Q3 | 4 | 75th percentile |
| IQR | 0 | Q3 minus Q1 |
| MAD | 0 | Median absolute deviation |
| 95.9% CI for median | 4 to 4 | Distribution-free |
| Outliers | 2, 3, 3, 5, 5, 5, 5 | Beyond 1.5 x IQR |
What it means: The median is 4 and the IQR is 0, because Q1, the median and Q3 are all 4. Here the mean also comes to exactly 4.00, so the two agree numerically, and that is the point worth noticing: the objection to the mean on a Likert scale is not that it gives a different number but that computing it assumes the categories are equally spaced, which has not been established. The median makes no such assumption, needs only that the responses can be ranked, and is what most reviewers expect for ordinal data.
How to write it: "Service ratings had a median of 4 (IQR 0, n = 20); the median is reported rather than the mean because the response scale is ordinal."
Five soil pH readings
Why a 95% confidence interval is impossible below six observations.
A pilot study measured pH at five points. The researcher wants a confidence interval for the median.
| Statistic | Value | Note |
|---|---|---|
| n | 5 | Number of values |
| Position (n+1)/2 | 3 | Where the median sits |
| Median | 6.4 | The middle value |
| Mean | 6.36 | For comparison |
| Mean vs median gap | 0.6% | Skew detector |
| Q1 | 5.75 | 25th percentile |
| Q3 | 6.95 | 75th percentile |
| IQR | 1.2 | Q3 minus Q1 |
| MAD | 0.5 | Median absolute deviation |
| 93.8% CI for median | 5.6 to 7.1 | Distribution-free, widest available |
| Outliers | none | Beyond 1.5 x IQR |
What it means: The median is 6.4, the third of five values. But no 95% interval exists: even taking the full range from 5.6 to 7.1 gives only 93.75% coverage, because with five observations the probability of all five falling on one side of the true median is 2 x (1/32) = 6.25%. The calculator returns the widest available interval and states its true coverage rather than pretending otherwise.
How to write it: "pH had a median of 6.4 (IQR 1.2, range 5.6 to 7.1, n = 5); no 95% confidence interval could be computed at this sample size."
A median that appears nowhere
When the answer is not one of your observations.
Six reaction times in milliseconds. There is no single middle value.
| Statistic | Value | Note |
|---|---|---|
| n | 6 | Number of values |
| Position (n+1)/2 | 3.5 | Where the median sits |
| Median | 304.5 | The middle value |
| Mean | 306.5 | For comparison |
| Mean vs median gap | 0.7% | Skew detector |
| Q1 | 294 | 25th percentile |
| Q3 | 316 | 75th percentile |
| IQR | 22 | Q3 minus Q1 |
| MAD | 11 | Median absolute deviation |
| 96.9% CI for median | 289 to 331 | Distribution-free |
| Outliers | none | Beyond 1.5 x IQR |
What it means: With six values the position is 3.5, so the median is the average of the third and fourth: (301 + 308) / 2 = 304.5. No one recorded 304.5, and that is perfectly correct. People sometimes assume the median must be an observed value; with an even count it usually is not.
How to write it: "Reaction time had a median of 304.5 ms (IQR 22.0, n = 6)."
Two populations mixed
The case both the median and the mean get wrong together.
Heights in centimetres from a mixed group, recorded without noting which subgroup each came from.
| Statistic | Value | Note |
|---|---|---|
| n | 12 | Number of values |
| Position (n+1)/2 | 6.5 | Where the median sits |
| Median | 167.5 | The middle value |
| Mean | 167.5 | For comparison |
| Mean vs median gap | 0% | Skew detector |
| Q1 | 154.5 | 25th percentile |
| Q3 | 180.5 | 75th percentile |
| IQR | 26 | Q3 minus Q1 |
| MAD | 13 | Median absolute deviation |
| 96.1% CI for median | 154 to 181 | Distribution-free |
| Outliers | none | Beyond 1.5 x IQR |
What it means: The median is 167.5 and the mean is 167.5. They agree perfectly, which would normally signal clean symmetric data. But look at the plot: there is nothing anywhere near 167.5. The data form two tight clusters around 155 and 180, and both averages land in the empty gap between them. The mean-median check cannot detect this, which is exactly why you must always plot your data.
How to write it: "Height showed a bimodal distribution with clusters near 155 cm and 180 cm; no single median was reported as it falls between the two groups."
Three field sites
Comparing medians across groups, and what that does not prove.
Tree diameter in centimetres at site A. Sites B and C are compared in the calculator above.
| Statistic | Value | Note |
|---|---|---|
| n | 14 | Number of values |
| Position (n+1)/2 | 7.5 | Where the median sits |
| Median | 34.5 | The middle value |
| Mean | 37.071 | For comparison |
| Mean vs median gap | 7.5% | Skew detector |
| Q1 | 26 | 25th percentile |
| Q3 | 45 | 75th percentile |
| IQR | 19 | Q3 minus Q1 |
| MAD | 9.5 | Median absolute deviation |
| 98.7% CI for median | 24 to 52 | Distribution-free |
| Outliers | none | Beyond 1.5 x IQR |
What it means: The median diameter is 34.5 cm against a mean of 37.07, a gap of 7.5%, indicating mild right skew from a few larger trees. Reporting both is honest here. When comparing sites, remember that different medians do not establish a real difference: for that you need a Mann-Whitney or Kruskal-Wallis test, and you should check that each site is not itself distorted.
How to write it: "Diameter at breast height had a median of 34.5 cm (IQR 19.0, n = 14) at site A."
🧪 13. Data Collection Protocol
Study design: the median assumes a set of independent observations measured on a scale that can at least be ranked. Unlike the mean it does not require an interval or ratio scale, so ordinal data are acceptable.
- Confirm the values can be ordered. That is the only scale requirement. Ranks, grades, Likert responses and pain scores all qualify, and for those the median is often the only strictly defensible average.
- Define the population and the unit of observation. Be explicit about whether one observation is one subject, one repeat reading, or an average of several. Mixing these inflates n and makes the confidence interval look narrower than it is.
- Randomise the selection. A median from a convenience sample is a robust summary of the wrong group. Robustness protects against outliers, not against bias.
- Plan the sample size against the interval you need. Below n = 6 no 95% confidence interval for the median exists at all. For a reasonably tight interval aim for 30 or more, and see table 11.3 for what each n actually delivers.
- Fix the measurement resolution. Aggressive rounding creates ties, which is not fatal for the median but can collapse the IQR to zero and make the outlier fences unusable.
- Record missing data as blank, never as zero. A zero is a real observation that shifts the ordering; a blank is correctly ignored. This is one of the few ways to corrupt a median without noticing.
- Decide the quartile convention in advance and write it in the protocol. The median is identical everywhere, but Q1 and Q3 are not, and an unstated convention makes your IQR irreproducible.
- Record raw values, not just summaries. If you keep only a frequency table you are forced into the grouped interpolation formula, which gives an estimate rather than the true median.
- Lay the data out in one column per group, exactly as below, ready to paste or upload here.
| Site A (cm) | Site B (cm) | Site C (cm) |
|---|---|---|
| 18 | 22 | 15 |
| 21 | 25 | 17 |
| 24 | 27 | 20 |
One column per group, one row per unit, numbers only below the header. Blank cells are ignored, so unequal group sizes are fine.
Pre-registration: state before collection whether you will report the median or the mean, and on what basis. Switching to the median after seeing that the mean was inconvenient is a real form of unintentional bias, and it is invisible in the final paper unless you declared the rule in advance.
Common collection mistakes:
- Recording missing values as zero, which shifts the ordering and drags the median down.
- Pooling two genuinely different populations, producing a median that describes neither.
- Treating repeat readings of one subject as independent observations.
- Discarding raw values and keeping only a frequency table, which forces an estimated median.
- Rounding so heavily that most values tie, collapsing the IQR to zero.
🎯 14. When to Use the Median
The median is the right choice more often than most people are taught, but it is not universally superior and knowing when it costs you something matters.
Use the median when:
- ✓ The data are skewed, as income, waiting times, survival and claim sizes always are.
- ✓ There are outliers you want to describe honestly rather than let dominate the summary.
- ✓ The data are ordinal, such as Likert scales, rankings or grades.
- ✓ You want a summary a single extreme value cannot move.
- ✓ Some values are censored, such as "over 100", where a mean cannot be computed at all but a median often can.
- ✓ You are reporting to a general audience, where "half were above and half below" is intuitive.
Prefer the mean when:
- ✗ The data are symmetric and clean, where the mean is more statistically efficient and gives more precision for the same n.
- ✗ You need a total, since the mean times n gives the sum and the median has no such identity.
- ✗ You plan a t-test, ANOVA or regression, all of which are built on means.
- ✗ Small shifts across the whole distribution matter, since the median can miss real change that does not cross the middle.
- ✗ The data are already known to be normally distributed, where the mean is the optimal estimator.
Real-world examples:
- Economics, median household income and median house price, both reported precisely because the mean misleads.
- Medicine, median survival time and median length of stay, always right skewed.
- Ecology, median body mass or count per plot, where a few large individuals dominate.
- Survey research, median Likert response, where a mean assumes equal spacing.
- Software engineering, median response time, and the p50 that sits alongside p95 and p99 in every latency dashboard.
- Education, median exam mark when a few very low scores would drag the mean below the typical student.
Decision rule: compute both. If they agree, report the mean with its standard deviation and mention the median. If they disagree by more than about 10%, lead with the median and its IQR and say why. If the data are ordinal, use the median regardless.
🔧 15. Troubleshooting and Common Errors
| Symptom | Likely cause | Fix |
|---|---|---|
| Result shows a dash or blank | Text, currency symbols or thousands separators in the pasted values | Strip non-numeric characters, use a full stop as the decimal separator, press Calculate again |
| The median is not one of my values | An even number of observations, so the two middle values were averaged | Correct behaviour, not an error. See table 11.2 |
| The median ends in .5 | Same cause, an even count of integers | Report it as is, or state that you rounded and to what |
| My median differs from a classmate | One of you forgot to sort, or included a different number of values | Compare n first. The median itself is identical in every piece of software |
| Q1 and Q3 differ from Excel | Different quartile convention | Switch the quartile method selector. The median is unaffected by this choice |
| IQR came out as zero | More than half the values are identical, common with rating scales | Not an error. Report the frequency distribution instead of a box plot |
| Everything is flagged as an outlier | The IQR is near zero, so the fences sit almost on the box | The fence rule breaks down when IQR approaches zero. Use a frequency table |
| No confidence interval is shown | Fewer than about six observations | No 95% interval exists at that n. The calculator gives the widest available and states its coverage |
| The CI coverage is not exactly 95% | The method counts whole observations, so coverage is discrete | Correct and unavoidable. Report the actual coverage achieved |
| Median seems too low | Missing values were recorded as zeros | Blanks are ignored; zeros are counted as real observations. Recode missing data |
| Mean and median agree but the plot looks wrong | Bimodal data, where both land in an empty gap between two clusters | The gap check cannot detect this. Look at charts 1 and 3 |
| R gives a bigger MAD than Python | R's mad() scales by 1.4826 by default | Use mad(x, constant = 1) in R to compare like with like |
| Charts do not render | The CDN script was blocked, or the calculator has not been run | Allow the Chart.js CDN and press Calculate; tables and working still work without it |
⚖ 16. Assumptions and Limitations
Assumptions
- The values can be ranked. Check the measurement scale. This is the only requirement, and it is why ordinal data are acceptable here but not for the mean.
- Observations are independent. Check the design. Repeated measurements of the same unit are not independent and make the confidence interval falsely narrow.
- The sample represents the population. Check the sampling frame. Robustness protects the median from outliers, not from selection bias.
- The sample is large enough for what you claim. Check n. Below six observations no 95% confidence interval exists, and below about ten the median shifts noticeably when one value changes.
- The data come from one population. Check chart 1. A bimodal dataset produces a median in the empty middle that describes nothing.
- For the confidence interval only, the distribution is continuous. Heavy ties make the interval conservative, so its true coverage exceeds the nominal level.
Limitations
- The median discards information. It uses only the middle position and ignores the magnitudes of everything else, which makes it less efficient than the mean on clean symmetric data.
- It does not add up. Total revenue is the mean order value times the count; there is no equivalent identity for the median, so it cannot be used to recover totals.
- It is insensitive to change in the tails. A policy that improves the worst-off quarter without moving anyone across the middle will not shift the median at all.
- It cannot detect bimodality. Two clusters either side of an empty middle produce a median that matches the mean perfectly while describing no observation.
- Most standard tests are built on means. If you need a t-test, ANOVA or regression, you need the mean, or a rank-based alternative such as Mann-Whitney.
- The confidence interval has discrete coverage. You cannot request exactly 95%; the achievable levels are set by the binomial distribution and the calculator reports what it actually reached.
- The grouped-data median is an estimate, since interpolating within the median class assumes values are spread evenly across it.
- This tool assumes an unweighted simple sample. Weighted, stratified and clustered survey designs need a design-consistent quantile estimator.
🏁 17. Conclusion
A median calculator does something deceptively modest: it sorts your numbers and reports the one in the middle. That modesty is the source of its power. Because the median depends on position rather than magnitude, no single observation, however extreme, can move it. You could replace your largest value with a billion and the median would not shift by a unit. No other common summary statistic offers that guarantee.
The habit worth building is to compute the median and the mean together every time, then compare them. When they sit close, your data are roughly symmetric and the mean is the more efficient summary. When they pull apart, the mean has been captured by a tail and the median is the honest choice. That comparison costs nothing, takes two seconds, and prevents the single most common misreporting in applied statistics, which is quoting a mean for skewed data and calling it typical.
Report the median with its interquartile range, exactly as you would report a mean with a standard deviation. A median alone tells the reader where the middle is but nothing about how tightly the data cluster around it, and a median with no n attached invites more confidence than it has earned. The confidence interval this calculator provides is worth including too, particularly because it is exact and assumption-free, which is a genuinely strong claim that most intervals cannot make.
Two cautions are worth carrying away. The first is that robustness protects you from outliers, not from bias: a median computed from the wrong sample is precisely the wrong answer. The second is that the mean-median comparison detects skew but not bimodality, and two clusters with an empty middle will produce a median and a mean that agree perfectly while both describe a value nobody recorded. Plot the data. The charts catch what the summary statistics cannot.
Paste your numbers into the calculator above, check the position box to see exactly which observation the median came from, read the recommendation before the answer, and copy whichever reporting sentence matches your journal. Then reach for this median calculator whenever a distribution looks lopsided, because that is precisely the situation the median was built for.
❓ 18. Frequently Asked Questions
Q1. What is the median?
The median is the middle value of a dataset once the values are sorted from smallest to largest. Half the observations lie at or below it and half at or above it. It is a measure of central tendency, like the mean, but based on position rather than magnitude.
Q2. How do you find the median?
Sort the values, then take the one at position (n + 1) ÷ 2. With an odd count that lands on a whole number and the median is an actual observation. With an even count it lands halfway, so you average the two values either side.
Q3. What is the median formula?
For an odd count the median is the value at position (n + 1) ÷ 2. For an even count it is the average of the values at positions n/2 and n/2 + 1. There is no single algebraic expression because the median is defined by position, not by arithmetic on all the values.
Q4. How do you find the median of an even number of values?
Take the two middle values and average them. For 2, 4, 5, 7, 8, 9, 12 and 15 the two middle values are 7 and 8, so the median is 7.5. Note that this means the median may be a number that appears nowhere in your data, which is correct.
Q5. Should I use the median or the mean?
Use the median when the data are skewed, contain outliers, or are ordinal. Use the mean when the data are symmetric and clean, since it is more efficient. The quickest test is to compute both: if they differ by more than about 10% of the median, the data are skewed and the median is the honest summary.
Q6. Why is the median better than the mean for income?
Because income distributions have a long right tail. A small number of very high earners pull the mean upward so that most households earn less than the "average" income, which makes it a poor description of a typical household. The median is unaffected by how high the top earners go, which is why every national statistics office reports median household income.
Q7. Is the median affected by outliers?
Essentially no. The median has a breakdown point of 50%, meaning you would have to corrupt half the data before you could move it arbitrarily. Change the largest value in 1, 2, 3, 4, 5 from 5 to 5000 and the mean jumps from 3 to 1002 while the median stays at exactly 3.
Q8. What should I report alongside the median?
The interquartile range and the sample size, at minimum. The convention is median (IQR), or median with the Q1 to Q3 pair in brackets. Reporting a median with no spread measure is as uninformative as reporting a mean with no standard deviation.
Q9. What is the interquartile range?
The IQR is Q3 minus Q1, the width of the middle 50% of your data. It is the median's natural spread partner because it shares the same robustness: built from positions rather than magnitudes, so extreme values cannot inflate it.
Q10. Can you calculate a confidence interval for the median?
Yes, and this calculator does. The method uses order statistics and the binomial distribution, which makes it exact and completely free of distributional assumptions. Because it counts whole observations the achievable coverage is discrete, so you rarely get exactly 95% and the calculator reports what it actually achieved.
Q11. Why can't I get a 95% confidence interval for a small sample?
Below about six observations no 95% interval exists, even using the full range from minimum to maximum. With five values the probability of all five falling on one side of the true median is 6.25%, so the widest possible interval only reaches 93.75% coverage. The calculator reports that honestly rather than pretending otherwise.
Q12. How do you find the median in Excel?
Use =MEDIAN(A2:A17). Note there is no MEDIANIF function, so for a conditional median use the array formula =MEDIAN(IF(B2:B50="Site A",A2:A50)). Section 8 covers this with spreadsheet screenshots.
Q13. How do you find the median in R?
Use median(x), and IQR(x) for the spread. Watch out for mad(x), which multiplies the median absolute deviation by 1.4826 by default; use mad(x, constant = 1) if you want the plain MAD. Section 9 has a complete script with a plot.
Q14. How do you find the median in Python?
Use np.median(x), or statistics.median(x) from the standard library. Unlike the mean's standard deviation there is no ddof equivalent to worry about, so Python agrees with Excel and R exactly. Section 10 has a complete script with a plot.
Q15. How do you find the median from a frequency table?
Use the interpolation formula: median = L + [(n/2 − CF) ÷ f] × w, where L is the lower boundary of the class containing the median, CF is the cumulative frequency before it, f is its frequency and w is the class width. The Grouped Frequency tab in section 2 does this and shows the working. Note it gives an estimate, not the exact median.
Q16. What is the median absolute deviation?
The MAD is the median of the absolute distances between each value and the median. It is the robust counterpart of the standard deviation. Multiplying by 1.4826 rescales it to estimate the SD for normal data, and unlike the SD a single outlier cannot inflate it.
Q17. Can the median be used for Likert scale data?
Yes, and it is usually the preferred choice. Likert categories are ordered but not necessarily equally spaced, so averaging their codes assumes something that has not been established. The median only requires that responses can be ranked, which they can, and reviewers commonly object to a mean Likert score for exactly this reason.
Q18. Why do my quartiles differ between programs when the median does not?
Because there is no single agreed definition of a quartile, and at least three conventions are in common use. The median is unambiguous and identical everywhere, but Q1 and Q3 can differ on small samples. Always state which quartile method you used.
Q19. How many values do I need for a reliable median?
At least six for any 95% confidence interval to exist at all, around ten to twenty for a reasonably stable estimate, and thirty or more if you want a reasonably tight interval. Table 11.3 shows exactly what coverage each sample size delivers.
Q20. Can I use this calculator for my thesis or published research?
Yes for exploratory work, teaching and checking hand calculations. For formal submission, reproduce the numbers in R, Python, SPSS or SAS and cite that software. You can cite this tool as StatsUnlock. (2026). Median calculator. https://statsunlock.com/median-calculator/
📑 19. Cite This Tool
StatsUnlock. (2026). Median calculator [Interactive statistical tool]. https://statsunlock.com/median-calculator/@misc{statsunlock_median_2026, title={Median Calculator}, author={{StatsUnlock}}, year={2026}, note={Interactive statistical tool}, url={https://statsunlock.com/median-calculator/}}Central tendency was summarised using the StatsUnlock Median Calculator (2026). For each group we report the median with the interquartile range and the sample size. Confidence intervals for the median were computed distribution-free from binomial order statistics, and the achieved coverage is reported because the attainable levels are discrete. Outliers were identified using Tukey fences at 1.5 times the interquartile range.🔗 20. Related Tools
Compute the mean alongside five other averages, and see the mean-median gap that tells you which to report.
Open the tool →The median plus both quartiles and the extremes, drawn as a full box plot with three quartile conventions.
Open the tool →When your data turn out symmetric enough for the mean, get its precision and confidence interval there.
Open the tool →Compare relative variability between groups measured on different scales.
Open the tool →📖 21. Glossary of Terms
| Term | Plain-English meaning |
|---|---|
| Breakdown point | How much of the data can be corrupted before a statistic becomes useless. 50% for the median, 0% for the mean. |
| Central tendency | The general idea of a typical or middle value in a dataset. |
| Confidence interval | A range of plausible values for the true population median, given your sample. |
| Coverage | The proportion of repeated samples whose interval would contain the true median. Discrete for order-statistic intervals. |
| Distribution-free | Requiring no assumption about the shape of the data. The median's confidence interval is distribution-free. |
| Grouped data | Data already sorted into classes with frequencies, where the raw values are no longer available. |
| Interquartile range (IQR) | Q3 minus Q1, the width of the middle half of the data. |
| MAD | Median absolute deviation, the median of the distances from the median. The robust cousin of the standard deviation. |
| Mean | The arithmetic average. Sensitive to extreme values in a way the median is not. |
| Median | The middle value of sorted data. Half the observations lie at or below it. |
| Ordinal data | Values with a clear order but not necessarily equal gaps, such as Likert responses. |
| Order statistic | A value identified by its rank position, such as the third smallest. |
| Outlier | A value beyond the fences at 1.5 times the IQR from the box. A signal to investigate, not to delete. |
| Percentile | The value below which a given percentage of the data falls. The median is the 50th percentile. |
| Position formula | (n + 1) ÷ 2, which locates the median in the sorted list. |
| Q1 and Q3 | The first and third quartiles, at the 25th and 75th percentiles. |
| Robust statistic | One that barely changes when a few extreme values change. |
| Skew | Asymmetry. Right skew pulls the mean above the median; left skew pulls it below. |
| Tie | Two or more observations with the same value. Many ties can collapse the IQR to zero. |
| Tukey fence | The outlier cut-off at 1.5 times the IQR beyond Q1 or Q3. |
📚 22. References
The following peer-reviewed references support the methods used in this median calculator, covering robust central tendency, distribution-free confidence intervals for the median, the median absolute deviation and best practice in reporting.
- Thompson, W. R. (1936). On confidence ranges for the median and other expectation distributions for populations of unknown distribution form. The Annals of Mathematical Statistics, 7(3), 122–128. https://doi.org/10.1214/aoms/1177732502
- Hettmansperger, T. P., & Sheather, S. J. (1986). Confidence intervals based on interpolated order statistics. Statistics & Probability Letters, 4(2), 75–79. https://doi.org/10.1016/0167-7152(86)90021-0
- Leys, C., Ley, C., Klein, O., Bernard, P., & Licata, L. (2013). Detecting outliers: Do not use standard deviation around the mean, use absolute deviation around the median. Journal of Experimental Social Psychology, 49(4), 764–766. https://doi.org/10.1016/j.jesp.2013.03.013
- Rousseeuw, P. J., & Croux, C. (1993). Alternatives to the median absolute deviation. Journal of the American Statistical Association, 88(424), 1273–1283. https://doi.org/10.1080/01621459.1993.10476408
- Wilcox, R. R., & Keselman, H. J. (2003). Modern robust data analysis methods: Measures of central tendency. Psychological Methods, 8(3), 254–274. https://doi.org/10.1037/1082-989X.8.3.254
- Hyndman, R. J., & Fan, Y. (1996). Sample quantiles in statistical packages. The American Statistician, 50(4), 361–365. https://doi.org/10.1080/00031305.1996.10473566
- Manikandan, S. (2011). Measures of central tendency: Median and mode. Journal of Pharmacology and Pharmacotherapeutics, 2(3), 214–215. https://doi.org/10.4103/0976-500X.83300
- Altman, D. G., & Bland, J. M. (1994). Statistics notes: Quartiles, quintiles, centiles, and other quantiles. BMJ, 309(6960), 996. https://doi.org/10.1136/bmj.309.6960.996
- Wan, X., Wang, W., Liu, J., & Tong, T. (2014). Estimating the sample mean and standard deviation from the sample size, median, range and/or interquartile range. BMC Medical Research Methodology, 14, 135. https://doi.org/10.1186/1471-2288-14-135
- Hozo, S. P., Djulbegovic, B., & Hozo, I. (2005). Estimating the mean and variance from the median, range, and the size of a sample. BMC Medical Research Methodology, 5, 13. https://doi.org/10.1186/1471-2288-5-13
- Tukey, J. W. (1977). Exploratory data analysis. Addison-Wesley. https://search.worldcat.org/title/3058187
- McGill, R., Tukey, J. W., & Larsen, W. A. (1978). Variations of box plots. The American Statistician, 32(1), 12–16. https://doi.org/10.1080/00031305.1978.10479236
- Jamieson, S. (2004). Likert scales: How to (ab)use them. Medical Education, 38(12), 1217–1218. https://doi.org/10.1111/j.1365-2929.2004.02012.x
- Norman, G. (2010). Likert scales, levels of measurement and the laws of statistics. Advances in Health Sciences Education, 15, 625–632. https://doi.org/10.1007/s10459-010-9222-y
- Huber, P. J., & Ronchetti, E. M. (2009). Robust statistics (2nd ed.). Wiley. https://doi.org/10.1002/9780470434697
- Weissgerber, T. L., Milic, N. M., Winham, S. J., & Garovic, V. D. (2015). Beyond bar and line graphs: Time for a new data presentation paradigm. PLOS Biology, 13(4), e1002128. https://doi.org/10.1371/journal.pbio.1002128
- Weisstein, E. W. (n.d.). Statistical median. MathWorld, A Wolfram Web Resource. https://mathworld.wolfram.com/StatisticalMedian.html
- American Psychological Association. (2020). Publication manual of the American Psychological Association (7th ed.). https://doi.org/10.1037/0000165-000
- NIST/SEMATECH. (2013). e-Handbook of statistical methods. National Institute of Standards and Technology. https://www.itl.nist.gov/div898/handbook/
- R Core Team. (2024). R: A language and environment for statistical computing. R Foundation for Statistical Computing. https://www.R-project.org/
