Beyond the average: five measures of spread every data scientist should know.
In Day 3, we learned how mean, median, and mode describe the centre of a dataset. But knowing the centre alone is like knowing a city's average temperature. It won't tell you whether you need a jacket or sunscreen on any given day. Today we look at the other half of the story: how spread out is the data?
Look at these five datasets. They all have the exact same mean, but they're clearly very different from each other.
Set 5 barely varies at all. Set 1 is spread out everywhere. If all you reported was "the mean," these five datasets would look completely identical on paper. Measures of dispersion are what show the real difference between them.
In this article we'll cover five key measures of spread:
Range is the simplest measure of spread there is. It's just the difference between the biggest and smallest values in a dataset.
Salaries (in USD) of 10 data scientists at a company:
[78.3k, 72k, 75k, 80k, 73.5k, 70k, 78k, 85k, 71k, 73k]
This tells us salaries span a $15,000 gap. Not a bad first impression.
Range has two big problems. First, it ignores every middle value. Only the max and the min decide it, nothing else in the dataset matters at all. Second, it's extremely sensitive to outliers, since one extreme value can throw the whole thing off.
Here's what happens if we swap the $85k salary for $300k:
[78.3k, 72k, 75k, 80k, 73.5k, 70k, 78k, 71k, 73k, 300k]
The range jumps from $15k to $230k because of one single outlier, even though the other nine salaries barely changed at all. This is exactly why we need measures that don't get fooled so easily.
Variance measures the average squared distance of each data point from the mean. Unlike range, it uses every single value in the dataset, which makes it a much more complete measure of spread.
There are two versions of the formula, depending on whether your data is the entire population or just a sample of it.
The key difference is dividing by n−1 instead of n for the sample version. This is called Bessel's correction. We first ran into this exact idea back in Day 1: a sample tends to slightly underestimate how spread out the real population is, so dividing by a smaller number corrects for that.
Dataset: [46, 69, 32, 60, 52, 41]
Step 1. Find the mean:
Step 2. Find each point's deviation from the mean, and square it:
| Data point | Deviation (x−mean) | Squared deviation |
|---|---|---|
| 46 | −4 | 16 |
| 69 | +19 | 361 |
| 32 | −18 | 324 |
| 60 | +10 | 100 |
| 52 | +2 | 4 |
| 41 | −9 | 81 |
| Total | 886 |
Step 3. Divide by n−1 (which is 5 here) to get the sample variance:
Without squaring, the positive and negative deviations would just cancel each other out, and the total would always land at (or near) zero, telling us nothing useful. Squaring makes every deviation positive, so they all add to the total spread instead of canceling it.
The result is in squared units. If your data is in dollars, variance comes out in "dollars squared," which isn't something anyone can picture. That's exactly why we take the square root next, to get standard deviation.
Standard deviation is simply the square root of variance. That one step brings the number back into the original units of your data, so you can read it right alongside the mean.
For our dataset [46, 69, 32, 60, 52, 41]:
In plain words: on average, the points in this set sit about 13.31 units away from the mean of 50. That's a sentence you can actually picture, which is more than you can say for "177.2 units squared."
Always pass ddof=1 in NumPy when you're working with a sample rather than the entire population. The default, ddof=0, computes the population version instead, and the difference isn't rounding error, it's a completely different formula. We covered exactly why back in Day 1: dividing by n−1 instead of n corrects for the fact that a sample tends to underestimate how spread out the full population really is. That correction has a name too: Bessel's correction.
| Use case | How SD helps |
|---|---|
| Understanding a distribution | High SD means widely spread data; low SD means tightly clustered data |
| Finance and risk | SD of stock returns is a common way to measure investment volatility |
| Quality control | Manufacturers use SD to check how consistent their products are |
| Machine learning | Feature scaling (standardization) uses the mean and SD together |
| Outlier detection | Values more than 2 to 3 SDs from the mean often get flagged as outliers |
Both variance and standard deviation are built around the mean. Since the mean itself gets thrown off by outliers, as we saw all through Day 3, variance and SD have that exact same problem too. One extreme value can make both of them much bigger than they should be.
This is why we need the next two measures.
MAD is a robust stand-in for standard deviation when your dataset has outliers. Instead of measuring the average distance from the mean, it measures the median distance from the median. That single swap, median instead of mean, is what makes it resistant to extreme values. We actually used MAD once already, back in Day 1's salary example. Here's the full recipe for calculating it yourself.
Step 1: Find the median of the dataset.
Step 2: Find the absolute deviation of each point from that median (just the distance, ignore the sign).
Step 3: Find the median of those absolute deviations. That number is your MAD.
Test scores: [94, 85, 78, 92, 100, 96]
Step 1, sort and find the median: sorted, this is [78, 85, 92, 94, 96, 100]. With 6 values, the median is (92 + 94) / 2 = 93.
Step 2, absolute deviations from 93: going through the sorted list, that's [15, 8, 1, 1, 3, 7].
Step 3, sort those and find their median: sorted, [1, 1, 3, 7, 8, 15]. The median of those 6 numbers is (3 + 7) / 2 = 5.
So the MAD is 5. On average, a score in this set sits 5 points away from the median, and that number barely budges even if one score in the set were wildly off.
Whenever your dataset has outliers or is heavily skewed. MAD shows up a lot in anomaly detection and in statistical models built specifically to resist extreme values.
IQR is another robust measure of spread. It focuses only on the middle 50% of the data, and completely ignores the top and bottom 25%, which is exactly where outliers tend to hide.
To find the IQR, you first need to understand quartiles: the values that cut a sorted dataset into four equal chunks.
| Quartile | What it is | Percentile |
|---|---|---|
| Q1 (lower quartile) | Median of the lower half of the data | 25th |
| Q2 (median) | Middle of the entire dataset | 50th |
| Q3 (upper quartile) | Median of the upper half of the data | 75th |
17 student test scores: [98, 94, 94, 62, 73, 87, 77, 68, 72, 85, 99, 100, 86, 60, 52, 100, 80]
Step 1, sort: [52, 60, 62, 68, 72, 73, 77, 80, 85, 86, 87, 94, 94, 98, 99, 100, 100]
Step 2, find Q2 (the median): with 17 values, the middle one is the 9th, so Q2 = 85.
Step 3, find Q1 and Q3: the lower half (the 8 values below the median) is [52, 60, 62, 68, 72, 73, 77, 80], so Q1 = (68 + 72) / 2 = 70. The upper half is [86, 87, 94, 94, 98, 99, 100, 100], so Q3 = (94 + 98) / 2 = 96.
Step 4, calculate IQR: IQR = 96 − 70 = 26.
The middle 50% of students scored within a 26 point range. The two extreme scores, 52 and 100, have zero say in that number.
Here's the gap the note above was talking about, and it's bigger than "slight." The manual method (sort the data, split it into two halves, find the median of each half) gave Q1=70 and Q3=96, so IQR=26. NumPy's default method gives Q1=72 and Q3=94, so IQR=22. That's an 18% difference, and neither answer is wrong. They're just two different ways of answering the same question: "what value sits 25% of the way through this data?" Different tools pick different answers to that question. We saw this exact same thing back in Day 1, with a different dataset. The lesson stays the same: check which method a tool uses before you compare its IQR to someone else's. A mismatch usually just means two different rulers, not a mistake.
IQR has a very common practical job: it defines the "fence rule" that box plots use to flag outliers.
Using the manual method's numbers (Q1=70, Q3=96, IQR=26):
Any point outside those two numbers gets flagged as a potential outlier. In this dataset, nothing falls below 31 or above 135, so no scores get flagged.
This is the exact rule that box plots use in Matplotlib, Seaborn, and pretty much every plotting library you'll ever touch.
A measure of spread only really means something when you report it next to a measure of central tendency. Here's why that matters.
Consider two companies, both with a mean salary of exactly $96,000:
Same mean, two completely different stories. That's why you should always report spread alongside centre, never one without the other. In practice, there's a simple rule for which pair to use:
Every time you compute a mean or median in a real project, follow it up immediately with a measure of spread. A central tendency reported on its own is an incomplete summary, and it can easily be a misleading one.
Quick reference:
Three questions to test whether this stuck.
Not necessarily. Range only looks at the two extreme points, the max and the min. Everything in between could be tightly bunched together in one dataset and scattered evenly across the whole range in the other. You'd need variance, SD, MAD, or IQR to actually tell the difference.
Something's wrong with the calculation, because standard deviation can never be negative. It comes from squaring deviations (which always gives a positive number or zero) and then taking a square root (which also never returns a negative number). If you see a negative SD, go check your code.
Because the whole point of MAD is to resist outliers, and the mean is exactly the number that outliers throw off. Using the median at both steps means one wild value can barely move the final answer, which is the entire reason MAD exists as an alternative to standard deviation.
Relative Measures of Dispersion: what to do when you need to compare spread across datasets that aren't even on the same scale.