Statistical Distributions Every Developer Should Know
Statistical distributions are mathematical models that describe how data values are spread. They are the foundation of hypothesis testing, confidence intervals, A/B testing, anomaly detection, and machine learning evaluation. This article covers the three essential distributions — normal, binomial, and Poisson — and how to use them for statistical inference with Python.
Normal (Gaussian) Distribution
The normal distribution is defined by its mean (the center) and standard deviation (the spread). Its bell-shaped curve appears everywhere because of the Central Limit Theorem: when you average many independent random variables, their sum approaches a normal distribution regardless of the original distributions. This theorem is why the normal distribution is used in t-tests, ANOVA, linear regression, and many other statistical methods even when the underlying data is not normally distributed — the estimators are approximately normal for large enough sample sizes. The 68-95-99.7 rule provides a quick reference: 68% of values fall within one standard deviation of the mean, 95% within two, and 99.7% within three.
import numpy as np
from scipy import stats
# Generate and analyze normal samples
np.random.seed(42)
samples = np.random.normal(loc=50, scale=10, size=1000)
# Descriptive statistics
print(f"Mean: {np.mean(samples):.2f} (theoretical: 50)")
print(f"Std: {np.std(samples):.2f} (theoretical: 10)")
print(f"Skewness: {stats.skew(samples):.2f} (0 = symmetric)")
print(f"Kurtosis: {stats.kurtosis(samples):.2f} (0 = normal tails)")
# Two-tailed test: is the mean significantly different from 52?
t_stat, p_value = stats.ttest_1samp(samples, 52)
print(f"t-test: t={t_stat:.2f}, p={p_value:.4f}")
if p_value < 0.05:
print("Mean is significantly different from 52 (reject H0)")
else:
print("No significant difference from 52 (fail to reject H0)")
# Confidence interval
ci = stats.norm.interval(0.95, loc=np.mean(samples), scale=stats.sem(samples))
print(f"95% CI for the mean: ({ci[0]:.1f}, {ci[1]:.1f})")
# The true mean (50) should be inside this interval 95% of the time
Binomial Distribution for A/B Testing
The binomial distribution models the number of successes in n independent trials with the same probability p. In A/B testing, each user visit is a trial, and a conversion (click, sign-up, purchase) is a success. The key question is whether the conversion rate for the treatment group (new design) is significantly higher than for the control group (current design). We use a chi-squared test or Fisher's exact test to compare two binomial proportions. The power of the test depends on the sample size and the effect size — tools like the statsmodels module can calculate the required sample size before running the experiment.
from scipy.stats import binom, chi2_contingency
import numpy as np
# A/B test results
control_visitors = 1000
control_conversions = 80 # 8% conversion rate
treatment_visitors = 1000
treatment_conversions = 110 # 11% conversion rate
# Contingency table
observed = np.array([
[control_conversions, control_visitors - control_conversions],
[treatment_conversions, treatment_visitors - treatment_conversions]
])
chi2, p_value, dof, expected = chi2_contingency(observed)
print(f"Chi-squared test: chi2={chi2:.2f}, p={p_value:.4f}")
if p_value < 0.05:
print("Treatment is statistically significantly better!")
else:
print("Difference is not statistically significant")
# Power analysis: how many visitors do we need?
from statsmodels.stats.power import NormalIndPower
from statsmodels.stats.proportion import proportion_effectsize
effect = proportion_effectsize(0.08, 0.11)
power_analysis = NormalIndPower()
required_n = power_analysis.solve_power(
effect_size=effect, power=0.8, alpha=0.05, ratio=1.0
)
print(f"Required sample per group for 80% power: {required_n:.0f}")
# Probability of observing 110+ conversions given 8% baseline
prob_110_or_more = 1 - binom.cdf(109, treatment_visitors, 0.08)
print(f"P(110+ conversions | baseline 8%) = {prob_110_or_more:.6f}")
Poisson Distribution for Count Data
The Poisson distribution models the number of events in a fixed interval when events occur independently at a constant average rate. It is the natural model for website requests per minute, errors per hour, customer arrivals per day, or defects per unit area. The Poisson has one parameter, lambda, which is both the mean and the variance. When the variance exceeds the mean (overdispersion), the negative binomial distribution is a better choice. A Poisson regression model is the standard approach for modeling count data with predictors.
from scipy.stats import poisson
# Monitoring a service: average 2 errors per hour
lambda_errors = 2.0
# Probability of exactly 0 errors in an hour
p0 = poisson.pmf(0, lambda_errors)
print(f"P(0 errors/hour) = {p0:.3f} ({100*p0:.1f}%)")
# Probability of 5+ errors in an hour (potential incident)
p5_or_more = 1 - poisson.cdf(4, lambda_errors)
print(f"P(5+ errors/hour) = {p5_or_more:.4f} ({100*p5_or_more:.2f}%)")
# If we observe 8 errors in one hour, is that anomalous?
p_8_or_more = 1 - poisson.cdf(7, lambda_errors)
print(f"P(8+ errors/hour | λ=2) = {p_8_or_more:.6f}")
if p_8_or_more < 0.01:
print("ALERT: Unusually high error rate detected!")
# Simulating request volumes for capacity planning
np.random.seed(42)
hourly_requests = np.random.poisson(lam=150, size=24*7) # week of data
print(f"Weekly traffic: mean={np.mean(hourly_requests):.0f}, "
f"max={np.max(hourly_requests)}, min={np.min(hourly_requests)}")
p99 = np.percentile(hourly_requests, 99)
print(f"99th percentile peak: {p99:.0f} requests/hour")
print(f"Provision for {p99:.0f} reqs/hour to cover 99% of traffic")
Understanding which distribution applies to your data is the first step in any statistical analysis. The normal distribution describes continuous measurements and sample means, the binomial models binary outcomes, and the Poisson models event counts. Python's scipy.stats and statsmodels libraries provide everything you need to compute probabilities, run hypothesis tests, and build regression models for all three distribution families.
Sampling Distributions and Central Limit Theorem
The Central Limit Theorem states that the sampling distribution of the mean approaches a normal distribution as sample size increases, regardless of the underlying population distribution. This is why the normal distribution appears so frequently—it describes the distribution of sample averages, not the raw data. This theorem justifies normal-based statistical tests even when the underlying data is not normal, provided sample sizes are adequate (typically n > 30 per group). The standard error quantifies how much sample means vary—increasing sample size reduces the standard error, making estimates more precise.
Real-World Applications of Statistical Distributions
Understanding distributions enables better data analysis. When building A/B testing systems, the binomial distribution models conversion counts, and the normal approximation applies with sufficient sample size. For queueing systems (customer service wait times, API response times), the Poisson distribution models arrival rates and the exponential distribution models inter-arrival times. For financial modeling, log-normal distributions model asset prices (returns are normally distributed, but prices are multiplicative). In reliability engineering, the Weibull distribution models time-to-failure for mechanical and electronic components. In natural language processing, word frequencies follow a Zipf distribution (power law). SciPy's stats module provides over 100 probability distributions with consistent APIs for PDF, CDF, random sampling, and parameter estimation using maximum likelihood estimation (MLE).
