SciPy と NumPy を使って、二項分布とポアソン分布の確率計算とシミュレーションを行います。理論値と乱数生成による実験結果を比較しながら、分布の性質を確認しましょう。
二項分布の確率計算
コインを 10 回投げて表が出る回数の分布を考えます。
import numpy as np import matplotlib.pyplot as plt from scipy import stats # 二項分布 B(n=10, p=0.5) n, p = 10, 0.5 binom_dist = stats.binom(n=n, p=p) # P(X = 5) を計算 print(f"P(X = 5) = {binom_dist.pmf(5):.4f}") # P(X <= 3) を計算 print(f"P(X <= 3) = {binom_dist.cdf(3):.4f}") # 期待値と分散 print(f"期待値: {binom_dist.mean():.2f}") print(f"分散: {binom_dist.var():.2f}")
二項分布のグラフと乱数シミュレーション
# 理論的な確率分布 x = np.arange(0, n + 1) pmf = binom_dist.pmf(x) # 乱数を 10000 回生成してシミュレーション np.random.seed(42) samples = binom_dist.rvs(size=10000) # グラフの描画 plt.figure(figsize=(10, 6)) plt.bar(x - 0.2, pmf, width=0.4, label='理論値', alpha=0.7) plt.hist(samples, bins=np.arange(-0.5, n + 1.5, 1), density=True, width=0.4, align='mid', label='シミュレーション', alpha=0.7) plt.xlabel('表の回数') plt.ylabel('確率') plt.title(f'二項分布 B({n}, {p})') plt.legend() plt.grid(True, alpha=0.3) plt.show()
シミュレーション結果が理論値とよく一致することが確認できます。
ポアソン分布の確率計算
1 時間あたり平均 4 件の電話がかかってくる場合を考えます。
# ポアソン分布 Po(λ=4) lam = 4 poisson_dist = stats.poisson(mu=lam) # P(X = 3) を計算 print(f"P(X = 3) = {poisson_dist.pmf(3):.4f}") # P(X >= 6) を計算 print(f"P(X >= 6) = {1 - poisson_dist.cdf(5):.4f}") # 期待値と分散(ポアソン分布では両方とも λ) print(f"期待値: {poisson_dist.mean():.2f}") print(f"分散: {poisson_dist.var():.2f}")
ポアソン分布のグラフと乱数シミュレーション
# 理論的な確率分布 x = np.arange(0, 15) pmf = poisson_dist.pmf(x) # 乱数を 10000 回生成 np.random.seed(42) samples = poisson_dist.rvs(size=10000) # グラフの描画 plt.figure(figsize=(10, 6)) plt.bar(x - 0.2, pmf, width=0.4, label='理論値', alpha=0.7) plt.hist(samples, bins=np.arange(-0.5, 15.5, 1), density=True, width=0.4, align='mid', label='シミュレーション', alpha=0.7) plt.xlabel('イベント数') plt.ylabel('確率') plt.title(f'ポアソン分布 Po({lam})') plt.legend() plt.grid(True, alpha=0.3) plt.show()
二項分布のポアソン近似
が大きく が小さいとき、二項分布はポアソン分布で近似できます。
# B(n=1000, p=0.004) と Po(λ=4) を比較 n_large, p_small = 1000, 0.004 binom_large = stats.binom(n=n_large, p=p_small) poisson_approx = stats.poisson(mu=n_large * p_small) x = np.arange(0, 15) plt.figure(figsize=(10, 6)) plt.bar(x - 0.2, binom_large.pmf(x), width=0.4, label=f'B({n_large}, {p_small})', alpha=0.7) plt.bar(x + 0.2, poisson_approx.pmf(x), width=0.4, label=f'Po({n_large * p_small})', alpha=0.7) plt.xlabel('x') plt.ylabel('確率') plt.title('二項分布のポアソン近似') plt.legend() plt.grid(True, alpha=0.3) plt.show()
二つの分布がほぼ重なっており、近似が有効であることが視覚的に確認できます。