Siksha Sarovar

Siksha Sarovar (sikshasarovar.com) is a free educational web application that helps students in India learn programming and prepare for academic and competitive exams. The platform offers structured coding courses (C, C++, Python, Java, HTML, CSS, PHP, Power BI, AI, Machine Learning, Data Science), complete university curriculum notes for BCA/MCA students with previous year question papers, Class 10 and Class 12 CBSE/HBSE school notes, and dedicated preparation material for SSC, UPSC, Banking, Railway and other government exams. Browsing the site is completely free and requires no account. Users may optionally sign in with Google solely to save their learning progress, quiz scores and personal preferences across devices.

Privacy Policy | Terms of Service | Contact Siksha Sarovar | About Siksha Sarovar

v4.0.9 · PWA
Siksha Sarovar logo
Siksha Sarovar
Your Learning Universe

Siksha Sarovar is a free e-learning platform for coding courses, BCA university notes and competitive exam preparation. Optional Google sign-in saves your learning progress across devices.

Initializing knowledge base…
Compiling modules 0%

Unit 2 — Box Plots

Lesson 21 of 46 in the free Introduction to Data Analytics notes on Siksha Sarovar, written by Rohit Jangra.

Box Plots (Box-and-Whisker Plots)

A box plot, invented by John Tukey, summarises a numeric distribution using the five-number summary and explicitly marks outliers. It is the most efficient chart for comparing distributions across groups.

Anatomy of a Box Plot

                    outlier
                       ○

              ┌────────┴────────┐  <- upper whisker (max within fence)
              │
        ┌─────┴─────┐  Q3 (75th percentile)
        │           │
        ├───────────┤  Median (Q2, 50th percentile)
        │           │
        └─────┬─────┘  Q1 (25th percentile)
              │
              └────────┬────────┘  <- lower whisker (min within fence)


   Box height  = IQR = Q3 − Q1  (the middle 50% of the data)
   Whiskers    extend to the most extreme point within 1.5 × IQR of the box
   Points beyond the whiskers are plotted individually as OUTLIERS

The Five-Number Summary

StatisticMeaning
MinimumSmallest value within the lower fence
Q125% of data lies below this
Median (Q2)50% of data lies below this
Q375% of data lies below this
MaximumLargest value within the upper fence

Outlier Fences

   IQR = Q3 − Q1

   Lower fence = Q1 − 1.5 × IQR
   Upper fence = Q3 + 1.5 × IQR

   Extreme (far) outliers use 3.0 × IQR instead of 1.5

Worked Example — By Hand

Data: 12, 15, 18, 22, 24, 25, 28, 30, 35, 42, 78 (n = 11, already sorted)

Median (Q2) = 6th value            = 25

Lower half: 12, 15, 18, 22, 24     ->  Q1 = 18
Upper half: 28, 30, 35, 42, 78     ->  Q3 = 35

IQR = 35 − 18 = 17

Lower fence = 18 − 1.5(17) = 18 − 25.5 = −7.5
Upper fence = 35 + 1.5(17) = 35 + 25.5 = 60.5

Outliers: 78  (it exceeds 60.5)

Whiskers: lower = 12 (smallest value ≥ −7.5)
          upper = 42 (largest value ≤ 60.5)

Five-number summary: 12, 18, 25, 35, 42  with 78 plotted as an outlier

Reading Shape from a Box Plot

Box Plot vs Histogram

BasisBox PlotHistogram
ShowsFive-number summary + outliersFull frequency distribution
Detects outliersExplicitly markedOnly implied by isolated bars
Reveals modalityNo — a bimodal distribution looks identical to a unimodal oneYes — peaks are visible
Comparing groupsExcellent — many boxes side by sidePoor — overlapping histograms get cluttered
Space requiredVery compactMore space per variable
Sensitive to bin choiceNoYes
Key limitation: a box plot cannot show multi-modality. Two datasets — one unimodal, one strongly bimodal — can produce identical box plots. Pair box plots with histograms or use a violin plot (a box plot with a mirrored KDE) when shape matters.

Python

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

data = pd.Series([12, 15, 18, 22, 24, 25, 28, 30, 35, 42, 78])

Q1, Q2, Q3 = data.quantile([0.25, 0.5, 0.75])
IQR = Q3 - Q1
lower, upper = Q1 - 1.5 * IQR, Q3 + 1.5 * IQR

print(f"Q1 = {Q1}, Median = {Q2}, Q3 = {Q3}, IQR = {IQR}")
print(f"Fences: [{lower}, {upper}]")
print("Outliers:", data[(data < lower) | (data > upper)].tolist())
# Q1 = 20.0, Median = 25.0, Q3 = 32.5, IQR = 12.5
# Fences: [1.25, 51.25]
# Outliers: [78]

print("Five-number summary:\n", data.describe()[["min", "25%", "50%", "75%", "max"]])
Note on quartile methods: pandas uses linear interpolation by default, which gives Q1 = 20.0 here, while the "median of the lower half" method taught in most textbooks gives Q1 = 18. Both are accepted; state which method you used.
# Single box plot
fig, ax = plt.subplots(figsize=(7, 5))
bp = ax.boxplot(data, vert=True, patch_artist=True, widths=0.4,
                boxprops=dict(facecolor="#168B99", alpha=0.7),
                medianprops=dict(color="#ef4444", linewidth=2),
                flierprops=dict(marker="o", markerfacecolor="#ef4444", markersize=8))
ax.set_title("Box Plot with One Outlier", fontweight="bold")
ax.set_ylabel("Value")
plt.show()
# COMPARING GROUPS — where box plots genuinely shine
tips = sns.load_dataset("tips")

fig, axes = plt.subplots(1, 3, figsize=(16, 4.5))

sns.boxplot(data=tips, x="day", y="total_bill", ax=axes[0], palette="Set2")
axes[0].set_title("Total Bill by Day")

sns.boxplot(data=tips, x="day", y="total_bill", hue="sex", ax=axes[1], palette="Set1")
axes[1].set_title("Total Bill by Day and Sex")

# Violin plot — box plot + distribution shape
sns.violinplot(data=tips, x="day", y="total_bill", ax=axes[2], palette="Set3", inner="box")
axes[2].set_title("Violin Plot — Shape Revealed")

plt.tight_layout()
plt.show()
# Group-wise five-number summary in numbers
summary = tips.groupby("day")["total_bill"].describe()[["min", "25%", "50%", "75%", "max"]].round(2)
summary["IQR"] = (summary["75%"] - summary["25%"]).round(2)
print(summary)
#       min    25%    50%    75%    max    IQR
# day
# Thur 7.51  12.44  16.20  20.16  43.11   7.72
# Fri  5.75  12.09  15.38  21.75  40.17   9.66
# Sat  3.07  13.91  18.24  24.74  50.81  10.83
# Sun  7.25  14.99  19.63  25.60  48.17  10.61
# INSIGHT: weekend bills are both higher (median) and more variable (IQR)
# Automated outlier report across every numeric column
def outlier_report(df):
    rows = []
    for col in df.select_dtypes(include=np.number).columns:
        Q1, Q3 = df[col].quantile([0.25, 0.75])
        IQR = Q3 - Q1
        lo, hi = Q1 - 1.5 * IQR, Q3 + 1.5 * IQR
        out = df[(df[col] < lo) | (df[col] > hi)][col]
        rows.append({"column": col, "Q1": round(Q1, 2), "Q3": round(Q3, 2),
                     "IQR": round(IQR, 2), "lower_fence": round(lo, 2),
                     "upper_fence": round(hi, 2), "n_outliers": len(out),
                     "pct": round(len(out) / len(df) * 100, 2)})
    return pd.DataFrame(rows)

print(outlier_report(tips))

When to Use a Box Plot

Use it whenPrefer something else when
Comparing a numeric variable across 2–20 groupsYou need to see the exact distribution shape → histogram/violin
Quickly detecting outliersThe sample is tiny (n < 10) → plot the raw points
Presenting a compact statistical summaryThe audience is non-technical and unfamiliar with quartiles
Checking a modelling assumption about spreadYou need frequencies/counts → histogram

Histograms and box plots describe one variable. The next chart handles two.