Comprehensive review guide with Python code examples
| Measure | Formula | When? |
|---|---|---|
| Mean | xΜ = Ξ£xα΅’ / n | Symmetric distributions |
| Median | Middle of sorted data | Skewed data, outliers |
| Mode | Most frequent value | Categorical data |
| Measure | = 0 | > 0 | < 0 |
|---|---|---|---|
| Skewness | Symmetric | Right-skewed | Left-skewed |
| Kurtosis | Normal | Heavy-tailed | Light-tailed |
Pythonimport numpy as np
from scipy import stats
data = [23, 45, 12, 67, 34, 89, 56, 78, 90, 43]
print(f"Mean: {np.mean(data):.2f}")
print(f"Median: {np.median(data):.2f}")
print(f"Std Dev: {np.std(data, ddof=1):.2f}")
print(f"Skewness: {stats.skew(data):.4f}")
print(f"Kurtosis: {stats.kurtosis(data):.4f}")
Central Limit Theorem: When nβ₯30, sample means are approximately normal.
Pythonfrom scipy.stats import norm, binom, poisson
print(f"P(Z < 1.96) = {norm.cdf(1.96):.4f}")
print(f"Binom(10,0.5) P(X=6) = {binom.pmf(6, 10, 0.5):.4f}")
print(f"Poisson(3) P(X=5) = {poisson.pmf(5, 3):.4f}")
How many standard deviations a value is from the mean.
| z | One-tailed P | Two-tailed P |
|---|---|---|
| 1.645 | 0.050 | 0.100 |
| 1.960 | 0.025 | 0.050 |
| 2.576 | 0.005 | 0.010 |
Pythonfrom scipy.stats import norm
x, mu, sigma = 85, 70, 10
z = (x - mu) / sigma
print(f"z = {z:.2f}")
print(f"P(Z < {z}) = {norm.cdf(z):.4f}")
print(f"P(Z > {z}) = {1 - norm.cdf(z):.4f}")
print(f"Two-tailed = {2*(1 - norm.cdf(abs(z))):.4f}")
print(f"Critical z (Ξ±=0.05) = {norm.ppf(0.975):.4f}")
| Level | z* |
|---|---|
| 90% | 1.645 |
| 95% | 1.960 |
| 99% | 2.576 |
Pythonimport numpy as np
from scipy import stats
data = np.random.normal(100, 15, size=50)
se = stats.sem(data)
ci = stats.t.interval(0.95, df=len(data)-1, loc=np.mean(data), scale=se)
print(f"Mean: {np.mean(data):.2f}")
print(f"95% CI: ({ci[0]:.2f}, {ci[1]:.2f})")
| Hβ True | Hβ False | |
|---|---|---|
| Reject Hβ | β Type I (Ξ±) | β Correct (Power) |
| Fail to Reject | β Correct | β Type II (Ξ²) |
Most reliable normality test (n < 5000). Hβ: Data is normal. p > 0.05 β Normal β
Pythonfrom scipy.stats import shapiro, normaltest
import numpy as np
normal_data = np.random.normal(50, 10, 100)
skewed_data = np.random.exponential(5, 100)
stat, p = shapiro(normal_data)
print(f"Shapiro β W={stat:.4f}, p={p:.4f}")
print("Normal β
" if p > 0.05 else "Not normal β")
Tests if groups have equal variances. Prerequisite for t-test and ANOVA.
Hβ: ΟβΒ² = ΟβΒ² | p > 0.05 β Homogeneous β
| Test | Advantage | Disadvantage |
|---|---|---|
| Levene | Doesn't assume normality | Slightly less powerful |
| Bartlett | Powerful under normality | Sensitive to violations |
Pythonfrom scipy.stats import levene
import numpy as np
group_a = np.random.normal(50, 10, 50)
group_c = np.random.normal(48, 25, 50)
stat, p = levene(group_a, group_c)
print(f"Levene W={stat:.4f}, p={p:.4f}")
print("Homogeneous β
" if p > 0.05 else "Heterogeneous β")
equal_var=False (Welch) for t-test, Kruskal-Wallis for ANOVA.Pythonfrom scipy.stats import ttest_1samp
scores = [78, 82, 85, 90, 74, 88, 92, 79, 83, 87]
t, p = ttest_1samp(scores, popmean=80)
print(f"t={t:.4f}, p={p:.4f} β {'Reject' if p<0.05 else 'Fail to reject'}")
Prerequisites: β Normality β‘ Variance homogeneity β’ Independence
Pythonfrom scipy.stats import ttest_ind, levene
import numpy as np
drug = np.random.normal(120, 15, 30)
placebo = np.random.normal(130, 15, 30)
_, p_lev = levene(drug, placebo)
t, p = ttest_ind(drug, placebo, equal_var=(p_lev > 0.05))
print(f"t={t:.4f}, p={p:.4f}")
print("Significant β
" if p < 0.05 else "Not significant β")
Pythonfrom scipy.stats import ttest_rel
before = [120, 135, 128, 140, 132, 145, 138, 130, 142, 136]
after = [115, 125, 122, 130, 128, 135, 130, 120, 132, 128]
t, p = ttest_rel(before, after)
print(f"t={t:.4f}, p={p:.4f} β {'Effective β
' if p<0.05 else 'Ineffective β'}")
Large-sample (nβ₯30) version of t-test when Ο is known.
Pythonimport numpy as np
from scipy.stats import norm
measurements = np.random.normal(503, 10, 50)
z = (np.mean(measurements) - 500) / (10 / np.sqrt(50))
p = 2 * (1 - norm.cdf(abs(z)))
print(f"z={z:.4f}, p={p:.4f}")
| Feature | Z-Test | T-Test |
|---|---|---|
| Ο known? | Yes | No |
| Sample | n β₯ 30 | Any |
| Distribution | Normal (CLT) | t distribution |
Compares 3+ group means. Hβ: ΞΌβ = ΞΌβ = ... = ΞΌβ
Pythonfrom scipy.stats import f_oneway
import numpy as np
a = np.random.normal(75, 8, 30)
b = np.random.normal(80, 8, 30)
c = np.random.normal(78, 8, 30)
F, p = f_oneway(a, b, c)
print(f"F={F:.4f}, p={p:.4f}")
from statsmodels.stats.multicomp import pairwise_tukeyhsd
data = np.concatenate([a, b, c])
groups = ['A']*30 + ['B']*30 + ['C']*30
print(pairwise_tukeyhsd(data, groups, alpha=0.05))
Is there a relationship between two categorical variables?
Pythonfrom scipy.stats import chi2_contingency, chisquare
import numpy as np
table = np.array([[50, 30], [20, 100]])
chi2, p, df, expected = chi2_contingency(table)
print(f"ΟΒ²={chi2:.4f}, p={p:.6f} β {'Related' if p<0.05 else 'Independent'}")
# Goodness of fit
observed = [18, 22, 20, 25, 15]
chi2, p = chisquare(observed, f_exp=[20]*5)
print(f"ΟΒ²={chi2:.4f}, p={p:.4f} β {'Biased' if p<0.05 else 'Fair'}")
| |r| | Interpretation |
|---|---|
| 0.00 β 0.29 | Weak |
| 0.30 β 0.69 | Moderate |
| 0.70 β 1.00 | Strong |
Pythonfrom scipy.stats import pearsonr, spearmanr
from sklearn.linear_model import LinearRegression
import numpy as np
x = np.random.uniform(1, 10, 50)
y = 50 + 4*x + np.random.normal(0, 5, 50)
r, p = pearsonr(x, y)
rho, p2 = spearmanr(x, y)
print(f"Pearson r={r:.4f}, Spearman Ο={rho:.4f}")
model = LinearRegression().fit(x.reshape(-1,1), y)
print(f"Ε· = {model.intercept_:.2f} + {model.coef_[0]:.2f}Β·x")
print(f"RΒ² = {model.score(x.reshape(-1,1), y):.4f}")
| Parametric | Non-Parametric | Scenario |
|---|---|---|
| Independent t | Mann-Whitney U | 2 independent groups |
| Paired t | Wilcoxon | 2 dependent groups |
| One-way ANOVA | Kruskal-Wallis | 3+ independent groups |
Pythonfrom scipy.stats import mannwhitneyu, wilcoxon, kruskal
import numpy as np
g1 = np.random.exponential(5, 30)
g2 = np.random.exponential(8, 30)
U, p = mannwhitneyu(g1, g2, alternative='two-sided')
print(f"Mann-Whitney U={U:.0f}, p={p:.4f}")
before = [85, 90, 78, 92, 88, 76, 95, 80, 83, 89]
after = [90, 95, 82, 96, 92, 82, 98, 86, 88, 93]
W, p2 = wilcoxon(before, after)
print(f"Wilcoxon W={W:.0f}, p={p2:.4f}")
p-value: "Is there a difference?" β Effect size: "How big?"
Pythonimport numpy as np
def cohens_d(g1, g2):
n1, n2 = len(g1), len(g2)
pooled = np.sqrt(((n1-1)*np.var(g1,ddof=1)+(n2-1)*np.var(g2,ddof=1))/(n1+n2-2))
return (np.mean(g1) - np.mean(g2)) / pooled
d = cohens_d(np.random.normal(120,15,30), np.random.normal(130,15,30))
print(f"Cohen's d = {d:.4f}")
Done BEFORE the test. 4 components (give 3, compute 4th):
Pythonfrom statsmodels.stats.power import TTestIndPower
analysis = TTestIndPower()
for d in [0.2, 0.5, 0.8]:
n = analysis.solve_power(effect_size=d, alpha=0.05, power=0.8)
print(f"d={d} β n={n:.0f} (per group)")
Pythonfrom statsmodels.stats.proportion import proportions_ztest, proportion_confint
from statsmodels.stats.proportion import proportion_effectsize
from statsmodels.stats.power import NormalIndPower
import numpy as np
# Control: 120/1000, Test: 145/1000
z, p = proportions_ztest([120,145], [1000,1000], alternative='smaller')
print(f"z={z:.4f}, p={p:.4f}")
if p < 0.05:
lift = (145/1000 - 120/1000) / (120/1000) * 100
print(f"β
Lift: +{lift:.1f}%")
effect = proportion_effectsize(0.10, 0.12)
n = NormalIndPower().solve_power(effect, alpha=0.05, power=0.80)
print(f"MDE 10%β12%: n = {n:.0f} per group")
| Pitfall | Solution |
|---|---|
| Peeking | Pre-determine n, wait |
| Multiple testing | Bonferroni: Ξ±_new = Ξ±/k |
| Simpson's paradox | Segment analysis |
| Novelty effect | Wait 2+ weeks |
Python# Medical test: 99% accuracy, 1% prevalence
p_sick = 0.01
p_pos = 0.99 * 0.01 + 0.01 * 0.99
posterior = (0.99 * 0.01) / p_pos
print(f"P(Sick | Positive) = {posterior:.2%}")
print("β Even 99% accurate test misleads with rare diseases!")
| # | Step | Tool |
|---|---|---|
| 1 | Identify data type | df.dtypes |
| 2 | Explore distribution | Histogram, QQ-plot |
| 3 | Test normality | shapiro() |
| 4 | Check variance | levene() |
| 5 | Apply test | Decision tree |
| 6 | Effect size | Cohen's d, Ξ·Β² |
| 7 | Report | p + effect + CI |