Chapter 1 · Solutions
Practice Challenges, Worked Answers ✅
Full solutions to the three "What Is Statistics?" challenges. Try them yourself first, then compare, the code is short and the goal is intuition.
Statistics, Data Science and AI: A Visual Handbook · John Fisher · 2026
⚙️ Setup¶
Same clean style as the chapter notebook.
In [1]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
NAVY="#0a1230"; INK="#1a2138"; INK_SOFT="#4a5578"
CYAN="#0891b2"; PURPLE="#7c3aed"; AMBER="#d97706"; GREEN="#059669"; PINK="#db2777"
GRID="#e6e9f2"
plt.rcParams.update({
"figure.facecolor":"white","axes.facecolor":"white","figure.dpi":110,
"font.size":11,"axes.edgecolor":GRID,"axes.linewidth":1.2,
"axes.grid":True,"grid.color":GRID,"axes.axisbelow":True,
"axes.spines.top":False,"axes.spines.right":False,
"axes.titlesize":14,"axes.titleweight":"bold","axes.titlecolor":INK,
"axes.labelcolor":INK_SOFT,"xtick.color":INK_SOFT,"ytick.color":INK_SOFT,"legend.frameon":False,
})
print("✅ Ready.")
✅ Ready.
CHALLENGE 1
Find the center
Daily customer counts for 10 days:
[12, 15, 12, 18, 20, 12, 16, 15, 14, 12]. Find the mean, median, and mode.In [2]:
days = pd.Series([12, 15, 12, 18, 20, 12, 16, 15, 14, 12])
mean = days.mean()
median = days.median()
mode = days.mode().iloc[0]
print(f"Sorted data : {sorted(days)}")
print(f"Mean : {mean:.1f} (sum {days.sum()} / {len(days)} days)")
print(f"Median : {median:.1f} (middle of the sorted values)")
print(f"Mode : {mode} (12 appears most often — 4 times)")
Sorted data : [12, 12, 12, 12, 14, 15, 15, 16, 18, 20] Mean : 14.6 (sum 146 / 10 days) Median : 14.5 (middle of the sorted values) Mode : 12 (12 appears most often — 4 times)
In [3]:
# Visualize: how often each count occurs, with the three measures marked
counts = days.value_counts().sort_index()
fig, ax = plt.subplots(figsize=(9,4.3))
ax.bar(counts.index, counts.values, color=AMBER, alpha=0.85, edgecolor="white", width=0.7)
for v, lab, c in [(mean,"Mean","%s"%PURPLE),(median,"Median","%s"%CYAN),(mode,"Mode","%s"%GREEN)]:
ax.axvline(v, color=c, ls="--", lw=2.4)
ax.text(v, ax.get_ylim()[1]*0.95, f" {lab}", color=c, fontweight="bold", va="top")
ax.set_title("Challenge 1 — Customer counts", loc="left")
ax.set_xlabel("Daily customer count"); ax.set_ylabel("Number of days")
ax.set_yticks(range(0,5))
plt.tight_layout(); plt.show()
Answer: Mean = 14.4, Median = 14.5, Mode = 12. The mode (12) sits below the mean because a couple of busy days (18, 20) pull the average up.
CHALLENGE 2
Measure the spread
Using the same 10 numbers, find the range and the standard deviation.
In [4]:
rng_val = days.max() - days.min() # range = max - min
std_pop = days.std(ddof=0) # population standard deviation
print(f"Max = {days.max()}, Min = {days.min()}")
print(f"Range : {rng_val}")
print(f"Standard deviation : {std_pop:.2f}")
print()
print("Interpretation: most days fall within about", f"{std_pop:.1f}", "of the mean (14.4),")
print("so a typical day sees roughly 12-17 customers — fairly tightly clustered.")
Max = 20, Min = 12 Range : 8 Standard deviation : 2.65 Interpretation: most days fall within about 2.7 of the mean (14.4), so a typical day sees roughly 12-17 customers — fairly tightly clustered.
In [5]:
# Show each day's distance from the mean (what standard deviation summarizes)
fig, ax = plt.subplots(figsize=(9,4.3))
idx = np.arange(1, len(days)+1)
ax.bar(idx, days.values - mean, color=[GREEN if v>=mean else PINK for v in days],
alpha=0.85, edgecolor="white")
ax.axhline(0, color=NAVY, lw=1.5)
ax.set_title("Challenge 2 — Each day's deviation from the mean", loc="left")
ax.set_xlabel("Day"); ax.set_ylabel("Customers above / below mean")
ax.set_xticks(idx)
plt.tight_layout(); plt.show()
Answer: Range = 8 (20 − 12), Standard deviation ≈ 2.6. A small standard deviation relative to the mean means the days are fairly consistent.
CHALLENGE 3
Make a bar chart
Favorite-pet votes: Dog 14, Cat 9, Fish 5, Bird 3. Draw a labeled bar chart.
In [6]:
pets = ["Dog", "Cat", "Fish", "Bird"]
votes = [14, 9, 5, 3]
colors = [CYAN, PURPLE, AMBER, GREEN]
fig, ax = plt.subplots(figsize=(8,4.6))
bars = ax.bar(pets, votes, color=colors, alpha=0.9, edgecolor="white", width=0.65)
# Label each bar with its value
for b, v in zip(bars, votes):
ax.text(b.get_x()+b.get_width()/2, v+0.3, str(v), ha="center", fontweight="bold", color=INK)
ax.set_title("Challenge 3 — Favorite Pet (class vote)", loc="left")
ax.set_xlabel("Pet"); ax.set_ylabel("Number of votes")
ax.set_ylim(0, 16)
plt.tight_layout(); plt.show()
print("Note: bars have GAPS because the data is categorical (a bar chart).")
print("If the x-axis were numeric ranges, touching bars would make it a histogram.")
Note: bars have GAPS because the data is categorical (a bar chart). If the x-axis were numeric ranges, touching bars would make it a histogram.
Answer: Dogs win with 14 votes. Because pets are categories, this is a bar chart (bars separated by gaps), not a histogram.
🎉 Nicely done!
You just computed center (mean/median/mode), spread (range/standard deviation), and built a categorical bar chart, the everyday tools of descriptive statistics. These exact skills power the data-cleaning and EDA work later in the book.
Statistics, Data Science and AI: A Visual Handbook · © 2026 John Fisher