Chapter 73 · Solutions
Resampling — Worked Solutions ✅
Five challenges, each verified in code.
⚙️ Setup¶
In [1]:
import numpy as np, pandas as pd
from scipy import stats
rng = np.random.default_rng(730)
BASE="https://raw.githubusercontent.com/johnfisher-ai/Statistics-Data-Science-AI-Visual-Book/main/data/"
def bootstrap(x, stat, B=10000):
n=len(x); idx=rng.integers(0,n,size=(B,n)); return stat(np.asarray(x)[idx], axis=1)
CHALLENGE 1
Bootstrap the standard error
From a sample of 80 from Normal(100,15), bootstrap the SE of the mean and compare to s/sqrt(n).
In [2]:
x=rng.normal(100,15,80); bm=bootstrap(x,np.mean)
print(f"bootstrap SE = {bm.std():.3f}, formula s/sqrt(n) = {x.std(ddof=1)/np.sqrt(80):.3f}")
bootstrap SE = 1.888, formula s/sqrt(n) = 1.905
CHALLENGE 2
Percentile CI for the mean
Build the bootstrap 95% percentile CI for the mean and compare to the t-interval.
In [3]:
lo,hi=np.percentile(bm,[2.5,97.5]); se=x.std(ddof=1)/np.sqrt(80); t=stats.t.ppf(0.975,79)
print(f"bootstrap CI [{lo:.2f}, {hi:.2f}]")
print(f"t-interval [{x.mean()-t*se:.2f}, {x.mean()+t*se:.2f}]")
bootstrap CI [96.26, 103.75] t-interval [96.21, 103.79]
CHALLENGE 3
CI for the median
On right-skewed lognormal data (n=150), build a bootstrap 95% CI for the median.
In [4]:
y=rng.lognormal(3,0.6,150); bmed=bootstrap(y,np.median)
print(f"median {np.median(y):.2f}, bootstrap 95% CI [{np.percentile(bmed,2.5):.2f}, {np.percentile(bmed,97.5):.2f}]")
median 19.30, bootstrap 95% CI [17.37, 22.91]
CHALLENGE 4
CI for a correlation
Bootstrap a 95% CI for the correlation between two related variables.
In [5]:
a=rng.normal(0,1,120); b=0.6*a+rng.normal(0,1,120); data=np.column_stack([a,b])
def corr(arr,axis): return np.array([np.corrcoef(arr[i,:,0],arr[i,:,1])[0,1] for i in range(arr.shape[0])])
n=len(data); idx=rng.integers(0,n,size=(5000,n)); bc=corr(data[idx],1)
print(f"r = {np.corrcoef(a,b)[0,1]:.3f}, bootstrap 95% CI [{np.percentile(bc,2.5):.3f}, {np.percentile(bc,97.5):.3f}]")
r = 0.571, bootstrap 95% CI [0.467, 0.666]
CHALLENGE 5
Real data: median salary
Load resampling-and-simulation--salaries.xlsx and build a bootstrap 95% CI for the median salary.
In [6]:
try: emp = pd.read_excel("../../data/resampling-and-simulation--salaries.xlsx", sheet_name="Employees")
except FileNotFoundError: emp = pd.read_excel(BASE+"resampling-and-simulation--salaries.xlsx", sheet_name="Employees")
sal=emp.annual_salary.values; bmed=bootstrap(sal,np.median,B=20000)
print(f"n={len(sal)}: median ${np.median(sal):,.0f}, bootstrap 95% CI [${np.percentile(bmed,2.5):,.0f}, ${np.percentile(bmed,97.5):,.0f}]")
n=300: median $107,650, bootstrap 95% CI [$101,400, $111,100]
Statistics, Data Science and AI: A Visual Handbook · © 2026 John Fisher