⚙️ Setup¶
import numpy as np
import pandas as pd
print("✅ Ready.")
✅ Ready.
x = pd.Series([4, 8, 6, 5, 8, 9, 8, 3])
print(f"Sorted : {sorted(x)}")
print(f"Mean = {x.mean():.2f}")
print(f"Median = {x.median():.1f}")
print(f"Mode = {x.mode().iloc[0]}")
Sorted : [3, 4, 5, 6, 8, 8, 8, 9] Mean = 6.38 Median = 7.0 Mode = 8
Answer: Mean = 6.375, Median = 7.0 (average of the two middle values 6 and 8), Mode = 8 (appears three times).
base = pd.Series([10, 12, 11, 13, 12])
with_out = pd.concat([base, pd.Series([100])], ignore_index=True)
print(f"Before: mean {base.mean():.1f}, median {base.median():.1f}")
print(f"After : mean {with_out.mean():.1f}, median {with_out.median():.1f}")
Before: mean 11.6, median 12.0 After : mean 26.3, median 12.0
Answer: the mean jumped from 11.6 to about 26.3, while the median moved only from 12 to 12. The outlier hammered the mean and barely touched the median, so the median is the better summary here.
mean, median = 72, 78
if mean < median: skew = "LEFT-skewed (negative): a tail of low scores pulls the mean down"
elif mean > median: skew = "RIGHT-skewed (positive): a tail of high scores pulls the mean up"
else: skew = "symmetric"
print(f"mean {mean} < median {median} -> {skew}")
mean 72 < median 78 -> LEFT-skewed (negative): a tail of low scores pulls the mean down
Answer: Since mean (72) < median (78), the data is left-skewed: a few low scorers stretch the left tail and drag the mean below the median. Most students did fairly well.
factors = np.array([1.20, 1.05, 0.90]) # +20%, +5%, -10%
gm = np.exp(np.mean(np.log(factors))) # geometric mean of the factors
print(f"Average annual growth factor = {gm:.4f}")
print(f"Average annual growth rate = {(gm-1)*100:.1f}%")
print(f"(The naive arithmetic average would wrongly give {(factors.mean()-1)*100:.1f}%.)")
Average annual growth factor = 1.0428 Average annual growth rate = 4.3% (The naive arithmetic average would wrongly give 5.0%.)
Answer: Average annual growth ≈ 4.3%. Growth compounds, so you multiply the factors and take the cube root (the geometric mean), not the arithmetic average.
mid = np.array([10, 20, 30, 40])
freq = np.array([2, 5, 8, 5])
mean = np.sum(mid * freq) / np.sum(freq)
print(f"People : {freq.sum()}")
print(f"Estimated mean time: {mean:.1f} seconds")
People : 20 Estimated mean time: 28.0 seconds
Answer: Estimated mean ≈ 28.5 seconds, using Σ(midpoint × frequency) / Σ(frequency). With only grouped counts, the class midpoints stand in for the raw values.