liveBook · Manning

Interquartile range

As explained in Grokking Statistics

The difference between the third and first quartiles, representing the spread of the middle half of observations.

The interquartile range (IQR) measures how spread out the middle half of a dataset is. Find the first quartile (the 25th percentile, Q1) and the third quartile (the 75th percentile, Q3), then subtract: IQR = Q3 − Q1. Because it concentrates on the middle 50% of values, it reduces the influence of unusually large or small observations. section 2.15

Imagine bar tabs of 7, 18, 19, 20, 21, 22, 25, 120, and 1,500. The middle quartiles are Q1 = 19 and Q3 = 25, so the IQR is 6. In plain English, the central half of tabs falls from 19 to 25, even though a $1,500 tab sits far beyond that typical range. section 2.15

import numpy as np

bar_tabs = [7, 18, 19, 20, 21, 22, 25, 120, 1500]

q25 = np.percentile(bar_tabs, 25)
q50 = np.percentile(bar_tabs, 50)
q75 = np.percentile(bar_tabs, 75)

# 19.0 21.0 25.0
print(q25, q50, q75)

Use NumPy’s percentile function to calculate Q1, the median, and Q3. Subtract the 25th-percentile result from the 75th-percentile result to obtain the IQR. section 2.15

Pair the IQR with the median when data are skewed. For tornado widths, the mean is about 215 yards while the median is 100 yards, reflecting a long right tail. The 25th and 75th percentiles—50 and 250 yards—show that the middle 50% spans 200 yards, a description less distorted by the widest tornadoes. section 2.20

import pandas as pd
import numpy as np

# Load the dataset
df = pd.read_csv("https://raw.githubusercontent.com/thomasnield/"
  "training-data-repository/refs/heads/main/TORNADO_TRX.csv")


# Group by TOR_F_SCALE and calculate mean, median, standard deviation for TOR_WIDTH
grouped_stats = df.groupby('TOR_F_SCALE')['TOR_WIDTH'].agg(
   p25=lambda x: np.percentile(x, 25),  # 25th percentile (Q1)
   median='median',                     # median
   p75=lambda x: np.percentile(x, 75),  # 75th percentile (Q3)
   iqr=lambda x: np.percentile(x, 75) - np.percentile(x,25) # IQR
).reset_index()

# Round the results for readability
grouped_stats = grouped_stats.round(2)


# Print the results
print("TOR_WIDTH Statistics by TOR_F_SCALE:")
print(grouped_stats)
# TOR_WIDTH Statistics by TOR_F_SCALE:
#   TOR_F_SCALE     p25  median     p75    iqr
# 0         EF0    30.0    50.0   100.0   70.0
# 1         EF1    80.0   150.0   300.0  220.0
# 2         EF2   200.0   400.0   792.5  592.5
# 3         EF3   400.0   700.0  1387.5  987.5
# 4         EF4  1000.0  1320.0  1575.0  575.0
# 5         EFU    20.0    30.0    50.0   30.0

For comparisons across categories, calculate Q1, median, Q3, and IQR separately with pandas groupby. This makes each tornado severity rating its own dataset for side-by-side spread comparisons. section 2.20

Quartiles are percentiles: the 25th, 50th, and 75th percentiles divide ordered data into four parts. Quantiles express the same idea on a 0-to-1 scale. Small datasets may require NumPy to interpolate percentile values, so check its estimation details when exact results matter. section 2.15

How Grokking Statistics covers it

How deep it goes
Defines IQR through quartiles, calculates it in NumPy and pandas, and notes percentile interpolation for small datasets.
Examples
Uses bar-tab values with an IQR of 6 and NOAA tornado widths ranging from 50 to 250 yards for the middle half.
What it assumes
Teaches quartiles from ordered-data cuts while assuming only basic Python use for the supplied calculations.
What you can do after
Apply it via NumPy and pandas to describe robust spread and compare grouped numeric data.
How it connects
Connects quartiles and percentiles to the median, quantiles, outliers, mean, standard deviation, histograms, and pandas groupby.

Also explained in

Compare how 7 books explain interquartile range →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Grokking Statistics. The section links point to the parts of the book it draws on.