Chapter 79 · Solutions
Chi-Square — Worked Solutions ✅
Five challenges, each verified in code.
⚙️ Setup¶
In [1]:
import numpy as np, pandas as pd
from scipy import stats
from scipy.stats.contingency import association
BASE="https://raw.githubusercontent.com/johnfisher-ai/Statistics-Data-Science-AI-Visual-Book/main/data/"
rng=np.random.default_rng(790)
CHALLENGE 1
Goodness-of-fit for a die
Test whether [18,22,16,20,14,10] (100 rolls) is consistent with a fair die.
In [2]:
obs=np.array([18,22,16,20,14,10]); exp=np.full(6,obs.sum()/6)
r=stats.chisquare(obs,exp); print(f"chi2={r.statistic:.2f}, df=5, p={r.pvalue:.4f}")
chi2=5.60, df=5, p=0.3471
CHALLENGE 2
Goodness-of-fit vs a claim
Observed [330,290,180,100]; claim 40/30/20/10. Test it.
In [3]:
obs=np.array([330,290,180,100]); exp=np.array([.4,.3,.2,.1])*obs.sum()
r=stats.chisquare(obs,exp); print(f"chi2={r.statistic:.2f}, p={r.pvalue:.4f}")
chi2=5.09, p=0.1651
CHALLENGE 3
Test of independence
For the table [[90,60,50],[40,80,70]], test independence and report dof.
In [4]:
chi2,p,dof,exp=stats.chi2_contingency([[90,60,50],[40,80,70]])
print(f"chi2={chi2:.2f}, dof={dof}, p={p:.4f}")
chi2=25.18, dof=2, p=0.0000
CHALLENGE 4
Cramer's V
For the table above, compute Cramer's V as an effect size.
In [5]:
t=np.array([[90,60,50],[40,80,70]]); V=association(t, method="cramer")
print(f"Cramer\u2019s V = {V:.3f}")
Cramer’s V = 0.254
CHALLENGE 5
Real data: channel by region
Load chi-square-tests--customer_channel.xlsx and test independence of region and preferred_channel.
In [6]:
try: d = pd.read_excel("../../data/chi-square-tests--customer_channel.xlsx", sheet_name="Customers")
except FileNotFoundError: d = pd.read_excel(BASE+"chi-square-tests--customer_channel.xlsx", sheet_name="Customers")
ct=pd.crosstab(d.region,d.preferred_channel); chi2,p,dof,_=stats.chi2_contingency(ct)
print(f"chi2={chi2:.2f}, dof={dof}, p={p:.2e}")
chi2=81.00, dof=9, p=1.02e-13
Statistics, Data Science and AI: A Visual Handbook · © 2026 John Fisher