Probabilities, critical values and simulations all start from a distribution object.
scipy.stats provides over a hundred distributions with one shared interface. Continuous ones include norm, t, expon, gamma, beta, lognorm; discrete ones include binom, poisson, geom. Each has these methods:
pdf(x)(orpmf(k)for discrete): density or probability at a point,cdf(x): P(X <= x);sf(x)= 1 - cdf, but accurate far in the tail,ppf(q): the quantile, inverse of the cdf;isf(q)inverse of sf,rvs(size=..., random_state=...): random samples,mean(),std(),interval(0.95),stats(moments="mvsk").
Every continuous distribution has loc and scale parameters that shift and stretch it. For the normal they are the mean and standard deviation; for the exponential, scale is 1/rate. Shape parameters come first: stats.gamma(a=2, scale=3).
Freezing fixes the parameters: d = stats.norm(loc=100, scale=15) then d.cdf(130), d.ppf(0.99). It reads better and avoids repeating parameters.
To sample reproducibly, pass a NumPy Generator: d.rvs(size=1000, random_state=np.random.default_rng(0)).
Use sf and logpdf/logsf rather than 1 - cdf or log(pdf) when values are tiny; they avoid rounding to zero.
Example
import numpy as np
from scipy import stats
iq = stats.norm(loc=100, scale=15) # frozen distribution
print(round(iq.cdf(130), 4)) # 0.9772 (P(IQ <= 130))
print(round(iq.sf(130), 4)) # 0.0228 (P(IQ > 130))
print(round(iq.ppf(0.99), 1)) # 134.9 (99th percentile)
print(np.round(iq.interval(0.95), 1)) # [ 70.6 129.4]
coin = stats.binom(n=10, p=0.5)
print(round(coin.pmf(5), 4)) # 0.2461 (exactly 5 heads)
sample = iq.rvs(size=5, random_state=np.random.default_rng(0))
print(sample.round(1)) # [101.9 98. 109.6 101.6 92. ]
print(stats.norm.sf(10), 1 - stats.norm.cdf(10)) # 7.61985302416047e-24 0.0Remember
pdf/pmf,cdf,sf,ppf,rvswork the same on every distributionlocshifts andscalestretches; freeze parameters for readability- Use
sfand log-methods for accurate tail probabilities
Watch out for
- Using
scaleas the rate forexpon; scale is 1/rate.