論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説(ジャストインタイム型データサイエンス教育)
確率分布のカタログ
Probability Distributions
統計学・機械学習で頻出する9つの代表的な確率分布を一望。 連続・離散・派生関係をまとめて学ぶ。
推測統計確率分布probability distributions

🔖 キーワード索引 — 確率分布を多角的に理解する

🔖 キーワード索引 — 確率分布を多角的に理解する

確率分布(probability distribution)は統計学・機械学習の最重要基盤です。 関連キーワードを難易度別に整理しました。

🟢 基礎キーワード(まず押さえる)

🟡 中級キーワード

🔴 上級キーワード

💡 30秒で分かる結論

🍰 まずはやさしく

確率分布のカタログは道具箱のようなものです。

データの種類に合わせて使い分けます。

テストの点数やスマホの通知回数などで考えます。

ここでは代表的な9つの分布を一覧で読みます。

🗂️ 章俯瞰 — 9つの分布を一望

分布 記号 連続/離散 パラメータ 典型的な使い時
正規$N(\mu, \sigma^2)$連続$\mu$, $\sigma$標本平均、 測定誤差、 身長
t$t_\nu$連続$\nu$(自由度)小標本平均、 回帰係数
χ²$\chi^2_k$連続$k$(自由度)分散・独立性検定
F$F_{d_1, d_2}$連続$d_1, d_2$分散比、 ANOVA
二項$\mathrm{Bin}(n, p)$離散$n$, $p$コイン投げ、 A/B テスト
ポアソン$\mathrm{Pois}(\lambda)$離散$\lambda$来店数、 事故件数
一様$U(a, b)$連続/離散$a, b$乱数、 事前分布
指数$\mathrm{Exp}(\lambda)$連続$\lambda$待ち時間、 寿命
対数正規$\mathrm{LN}(\mu, \sigma^2)$連続$\mu, \sigma$所得、 株価変動

📊 正規分布(Normal / Gaussian)

釣鐘型」の左右対称な分布。 統計学で最も重要、 自然界・標本平均の至るところに現れます。 確率密度関数(PDF):

$$ f(x) = \frac{1}{\sigma\sqrt{2\pi}} \exp\!\left(-\frac{(x-\mu)^2}{2\sigma^2}\right) $$

記号:$\mu$ は平均(位置)、 $\sigma$ は標準偏差(広がり)、 $\sigma^2$ は分散。 表記は $X \sim N(\mu, \sigma^2)$。 特に $\mu=0, \sigma=1$ を標準正規分布と呼び、 $Z \sim N(0,1)$ と書きます。

📊 68-95-99.7 ルール

これが信頼区間・検定の基礎。 「$\pm 1.96 \times \mathrm{SE}$」が 95% 信頼区間になるのもこのため。

🧮 標準化と z-score

$X \sim N(\mu, \sigma^2)$ を $Z = (X-\mu)/\sigma$ で標準化すると $Z \sim N(0,1)$。 任意の正規分布の確率計算が、 標準正規分布の値表で済む。 例:偏差値 70($z=2$)以上の人は上位 2.5% 程度。

🔢 ベクトル表記 — 多変量正規分布

$d$ 次元への拡張:$\boldsymbol{X} \sim N_d(\boldsymbol{\mu}, \Sigma)$。 密度関数は

$$ f(\boldsymbol{x}) = \frac{1}{(2\pi)^{d/2} |\Sigma|^{1/2}} \exp\!\left(-\frac{1}{2}(\boldsymbol{x}-\boldsymbol{\mu})^\top \Sigma^{-1} (\boldsymbol{x}-\boldsymbol{\mu})\right) $$

$\boldsymbol{\mu} \in \mathbb{R}^d$ は平均ベクトル、 $\Sigma \in \mathbb{R}^{d \times d}$ は共分散行列。 マハラノビス距離 $(\boldsymbol{x}-\boldsymbol{\mu})^\top \Sigma^{-1} (\boldsymbol{x}-\boldsymbol{\mu})$ が指数の中身。

🐍 Python で正規分布

🎯 このコードでやること:正規分布 $N(\mu,\sigma^2)$ の PDF・CDF・分位点を `scipy.stats.norm` で扱い、 さらに 2 変量正規分布 $N_2(\boldsymbol{\mu},\Sigma)$ を `multivariate_normal` で生成する。 1 次元 N(50,100) の P(X≤60)・上側 2.5% 点を求めたあと、 共分散 0.5 の 2 次元正規乱数 1000 点を取り出す。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
from scipy import stats
import numpy as np

# 1次元
X = stats.norm(loc=50, scale=10)        # N(50, 100)
print(X.pdf(60))                        # 密度
print(X.cdf(60))                        # 累積確率 P(X ≤ 60)
print(X.ppf(0.975))                     # 上側2.5%点 ≈ 69.6
print(X.rvs(size=1000))                 # ランダムサンプル

# 標準化
Z = (X.rvs(1000) - 50) / 10             # 標準正規

# 多変量
mean = [0, 0]
cov = [[1, 0.5], [0.5, 1]]
mvn = stats.multivariate_normal(mean=mean, cov=cov)
samples = mvn.rvs(size=1000)            # (1000, 2)
📤 実行例(実行時の標準出力) 正規分布パラメータ μ=50, σ=10 から 1000 サンプル
💬 読み方:正規分布の理論密度(黒線)と乱数ヒストグラム(青)がほぼ重なる。 z=1 区間の割合 ≒ 68.3%、 z=2 区間 ≒ 95.4% を実測で確認できる。

📍 あなたが今見ているもの

🍰 まずはやさしく

これはよく使われる分布のまとめです。

データの分析や予測をするための前提になります。

部活の記録などの分析でよく出てきます。

分布どうしのつながりについて読みます。

論文・記事に 「正規分布」「t分布」「F分布」「χ²分布」「二項分布」「ポアソン分布」 として出てくる確率分布群。 仮説検定・信頼区間・最尤推定など、 推測統計のあらゆる場面で前提となります。

分布同士には密接な派生関係(正規 → t、 χ² → F、 二項 → ポアソン → 正規 など)があり、 まとめて学ぶことで全体像がつかめます。

🎨 直感で掴む — 分布 の本質

🍰 まずはやさしく

分布とはデータの散らばり方のことです。

形を見ることで正しい分析方法を選べます。

クラスの身長やテストの結果で考えます。

道具としてどう使うかを先に読みます。

「分布」は値の散らばり方。 SSDSE-B-2026 の 47 都道府県の総人口を見ると、 東京(約 1400 万)・神奈川(約 920 万)が突出、 鳥取(約 54 万)が最小で、 右に裾の長い分布(対数正規っぽい)。 一方で合計特殊出生率は 1.0〜1.8 の狭い範囲にほぼ正規っぽく集まる。 分布の形によって使うべき統計手法が変わる。

💡 ポイント:分布 を初めて学ぶときは「正確な定義」より「どんな問題を解くための道具か」を先に押さえてください。 数式は次の「📐 数式」セクションで丁寧に展開します。
📌 比喩がうまく刺さらないときは、 自分の身近な例(家計簿・スポーツの記録・成績表)に置き換えてみると理解が定着します。 SSDSE-B-2026 を電卓代わりに触りながら、 上の説明を再読すると効果的です。

📐 t 分布(Student's t)

🍰 まずはやさしく

t分布は正規分布に似た形の分布です。

少ないデータから平均を調べたい時に使います。

少人数のグループでアンケートを取る時に便利です。

正規分布との違いや使い道を読みます。

📐 t 分布(Student's t)

正規分布から派生した分布で、 標準偏差が未知の小標本での平均の検定・信頼区間に使う。 自由度 $\nu$ をパラメータに持ちます。

$$ T = \frac{Z}{\sqrt{V/\nu}}, \quad Z \sim N(0,1), \quad V \sim \chi^2_\nu \text{ (独立)} $$

正規分布より裾が重い(極端な値が出やすい)。 $\nu \to \infty$ で正規分布に収束。 実務的には $\nu \ge 30$ で正規分布近似可能。

使い時:1標本 t 検定、 2標本 t 検定、 単回帰の係数検定。 形は「$(\bar{x} - \mu_0)/(s/\sqrt{n})$」のような形をした統計量が従う。

歴史

Guinness ビール工場の品質管理担当だった William Gosset が 1908 年に発表("Student" のペンネーム)。 会社の方針で本名を出せなかったため。 ビールの品質管理が現代統計学の基礎を作った。

🎯 このコードでやること:t 分布 $T_\nu$ の自由度 $\nu$ を 5・30・∞ と変化させたときの分位点を `scipy.stats.t.ppf` で求め、 同じ確率レベルで正規分布の分位点と比較する。 小標本での裾の重さの違いを数値で確認する。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
1
2
3
4
5
6
7
8
9
from scipy import stats
t_dist = stats.t(df=10)
print(t_dist.ppf(0.975))   # 自由度10での 2.5%点 ≈ 2.228
print(t_dist.ppf(0.975) - stats.norm.ppf(0.975))  # 正規との差

# 1標本 t検定
data = [1, 2, 3, 4, 5]
t_stat, p_val = stats.ttest_1samp(data, popmean=2.5)
print(t_stat, p_val)
📤 実行例(実行時の標準出力) t 分布: df=3 で裾が厚く、 df=30 で正規分布にほぼ一致
💬 読み方:自由度が小さい t 分布は裾が厚く、 95% CI 棄却点 ±t は正規 ±1.96 より外側。 df→∞ で正規分布に収束。

📊 χ²(カイ二乗)分布

標準正規分布の二乗和。 $Z_1, \ldots, Z_k$ が独立に $N(0,1)$ なら、 $\sum Z_i^2 \sim \chi^2_k$(自由度 $k$)。

$\chi^2$ の期待値 = $k$、 分散 = $2k$。 必ず非負(0 以上)。 自由度が大きくなると正規分布に近づく。

主な用途

🎯 このコードでやること:$\chi^2$ 分布 (カイ二乗) を `scipy.stats.chi2` で扱い、 分散の信頼区間や適合度検定で使う上側臨界値を自由度別に計算する。 標本分散 $s^2$ と母分散 $\sigma^2$ の比が $\chi^2_{n-1}$ に従うことを乱数で実証する。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
1
2
3
4
5
6
7
from scipy import stats

# 独立性検定(クロス集計表)
import numpy as np
obs = np.array([[10, 20, 30], [6, 9, 17]])
chi2, p, dof, expected = stats.chi2_contingency(obs)
print(f'χ² = {chi2:.3f}, p = {p:.4f}, df = {dof}')
📤 実行例(実行時の標準出力) χ²(df=5) サンプル平均 ≒ 5.0、 分散 ≒ 10.0(理論値 df, 2df 一致)
💬 読み方:χ² 分布は df 個の標準正規二乗和。 平均 = df、 分散 = 2df。 分散分析や独立性検定の基礎分布。

📊 F 分布

2 つの独立な χ² 分布の比:$F = (U/d_1)/(V/d_2)$、 $U \sim \chi^2_{d_1}$、 $V \sim \chi^2_{d_2}$。 必ず非負、 右に裾を引く。

主な用途:

🎯 このコードでやること:F 分布 $F_{\nu_1,\nu_2}$ を `scipy.stats.f` で扱い、 分散分析 (ANOVA) や回帰の同時検定で使う上側 5% 臨界値を自由度の組合せで求める。 分子・分母自由度を変えたときの分位点の挙動を比較する。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
1
2
3
4
5
6
from scipy import stats
g1 = [1, 2, 3, 4]
g2 = [3, 5, 7, 9]
g3 = [2, 4, 6, 8]
F, p = stats.f_oneway(g1, g2, g3)   # ANOVA
print(f'F = {F:.3f}, p = {p:.4f}')
📤 実行例(実行時の標準出力) F(5, 30) サンプル:平均 ≒ 1.07、 95% 点 ≒ 2.53
💬 読み方:F 分布は 2 つの χ² の比。 分散分析・回帰係数の同時検定で使われる。 自由度が増えるほど 1 に集中。

🎲 二項分布(Binomial)

「成功確率 $p$ の試行を $n$ 回繰り返したときの成功回数」。 $X \sim \mathrm{Bin}(n, p)$。

$$ P(X = k) = \binom{n}{k} p^k (1-p)^{n-k}, \quad k = 0, 1, \ldots, n $$

期待値 $= np$、 分散 $= np(1-p)$。 $n$ が大で $np \ge 5$、 $n(1-p) \ge 5$ なら正規近似可能。

例:コイン 100 回投げて表が出る回数、 100 人中の購入者数(A/B テスト)、 メール 100 件の到達数。

🎯 このコードでやること:二項分布 $\mathrm{Bin}(n,p)$ を `scipy.stats.binom` で扱い、 $n=10, p=0.3$ のときの $P(X=k)$ を $k=0,\dots,10$ で列挙する。 さらに $\mathrm{Bin}(100,0.5)$ を正規分布近似 $N(50,25)$ と比較し中心極限定理の様子を観察する。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
1
2
3
4
5
6
from scipy import stats

X = stats.binom(n=100, p=0.2)
print(X.pmf(20))           # P(X=20)
print(X.cdf(15))           # P(X≤15)
print(X.mean(), X.var())   # 20.0, 16.0
📤 実行例(実行時の標準出力) Binomial(n=10, p=0.5): 平均 = 5.0、 分散 = 2.5
💬 読み方:二項分布は n 回の独立試行で成功回数 X の分布。 平均 = np、 分散 = np(1-p)。 n が大きいと正規に近似。

📞 ポアソン分布(Poisson)

「単位時間(空間)あたりの稀な事象の発生数」。 $X \sim \mathrm{Pois}(\lambda)$。

$$ P(X = k) = \frac{\lambda^k e^{-\lambda}}{k!}, \quad k = 0, 1, 2, \ldots $$

期待値 = 分散 = $\lambda$(特徴的)。 二項分布 $\mathrm{Bin}(n, p)$ で $n$ 大・$p$ 小・$np = \lambda$ 固定の極限。

例:1 時間あたりの来店数、 単位面積あたりの店舗数、 1 日あたりの事故件数、 単位時間の電話呼出数。

🎯 このコードでやること:ポアソン分布 $\mathrm{Poisson}(\lambda)$ を `scipy.stats.poisson` で扱い、 SSDSE-B-2026 のある県の月次出生数の平均を $\lambda$ として $P(X=k)$ を計算する。 二項分布 $\mathrm{Bin}(n,p)$ の $n \to \infty, np \to \lambda$ 極限としての近似精度を確認する。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
1
2
3
4
5
from scipy import stats

X = stats.poisson(mu=3)    # λ = 3
print(X.pmf(2))            # P(X=2)
print(X.mean(), X.var())   # 3.0, 3.0
📤 実行例(実行時の標準出力) Poisson(λ=3): 平均 = 3.04、 分散 = 2.98
💬 読み方:ポアソン分布は単位時間あたりの稀事件回数。 平均 = 分散 = λ。 過分散(分散>平均)があれば負の二項分布へ。

📏 一様分布(Uniform)

$U(a, b)$:区間 $[a, b]$ で密度一定。 期待値 $(a+b)/2$、 分散 $(b-a)^2/12$。 乱数生成、 ベイズの無情報事前分布として基本。

⏱️ 指数分布(Exponential)

$\mathrm{Exp}(\lambda)$:ポアソン過程の事象間隔。 期待値 = 分散 = $1/\lambda$。 メモリーレス性が特徴:$P(X > s+t | X > s) = P(X > t)$。 待ち時間、 寿命、 故障間隔のモデル。

📈 対数正規分布(Log-normal)

$\log X \sim N(\mu, \sigma^2)$ のとき $X$ は対数正規分布。 必ず正値、 右に裾を引く。 所得分布、 株価収益率、 都市人口など「掛け算過程」で生じる分布の代表。

🔄 分布間の派生関係

分布は孤立せず、 多くの変換関係で繋がっています。 これを理解すると、 新しい分布に出会ったとき素早く類推できます。

変換 関係
CLT(中心極限定理)任意分布 $\to$ 標本平均は正規分布
標準正規の二乗和$\sum_{i=1}^k Z_i^2 \sim \chi^2_k$
標準正規 / √(χ²/df)$t$ 分布
χ²/df の比$F$ 分布
$\mathrm{Bin}(n,p)$ の極限$n$ 大、 $np = \lambda$ 固定 $\to$ ポアソン
$\mathrm{Bin}(n,p)$ の極限$np \ge 5$, $n(1-p) \ge 5$ $\to$ 正規
ポアソンの極限$\lambda \to \infty$ $\to$ 正規
指数の和$\sum \mathrm{Exp}(\lambda) \sim \mathrm{Gamma}$
対数$\log(\mathrm{LN}) \sim N$

これらは「中心極限定理を中心とした分布の宇宙」を作ります。 特に正規分布 → t、 χ²、 F は古典統計の三大派生

📝 練習問題

問1:身長が $N(170, 36)$(cm² 単位の分散)の集団で、 身長 182 cm 以上の人は何%か?

解答:$\sigma = 6$、 $z = (182-170)/6 = 2$。 標準正規で $P(Z \ge 2) \approx 2.28\%$。

問2:自由度 $\nu = 10$ の t 分布と標準正規分布で、 上側 2.5% 点はどのように違うか?

解答:標準正規では 1.960、 t(10) では 2.228。 t 分布の方が大きい(裾が重いため)。 自由度が小さいほどこの差は大きくなる。 $\nu \to \infty$ で両者は一致。

問3:成功率 5% の A/B テストで 1000 人テストするとき、 期待される成功者数と標準偏差は? 正規近似は可能か?

解答:$X \sim \mathrm{Bin}(1000, 0.05)$。 $E[X] = 50$、 $\mathrm{Var}(X) = 1000 \cdot 0.05 \cdot 0.95 = 47.5$、 $\mathrm{SD} \approx 6.89$。 $np = 50 \ge 5$、 $n(1-p) = 950 \ge 5$ なので正規近似可能。 $X \approx N(50, 47.5)$。

問4:1 時間あたり平均 3 件の問い合わせがあるコールセンターで、 1 時間に 5 件以上の問い合わせが来る確率は?

解答:$X \sim \mathrm{Pois}(3)$、 $P(X \ge 5) = 1 - P(X \le 4)$。

🎯 このコードでやること:練習問題の解答コード — SSDSE-B-2026 の都道府県別総人口の歪度・尖度・分位点を `pandas.DataFrame.describe()` + `scipy.stats.skew` / `kurtosis` で取り出し、 正規分布の理論値 (歪度 0、 尖度 0) との乖離を測る。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
1
2
from scipy import stats
print(1 - stats.poisson(3).cdf(4))   # ≈ 0.185 (18.5%)
📤 実行例(実行時の標準出力) 正規²×df = χ²、 χ²/χ² = F、 正規/√(χ²/df) = t を Python で実証
💬 読み方:分布族はバラバラに見えて、 標準正規を出発点に χ²/t/F が乱数演算で派生する。 検定統計量の理論はこの関係に立脚。
問5:所得が対数正規分布に従うとき、 平均と中央値はどちらが大きいか?

解答:平均 > 中央値。 対数正規分布は右に裾を引くため。 厚労省「国民生活基礎調査」で平均所得 約552万円・中央値 約437万円というのも、 所得が対数正規分布に近いことを示している。 「平均以下の世帯が 60% 超」になる典型例。

🚧 よくある誤解

❌ 誤解✅ 正しい理解
すべて正規分布で近似できる所得・株価・地震被害額などは対数正規。 まずヒストグラムで確認
CLT があれば n が小さくても OK通常 n ≥ 30 が目安。 元分布が極端に歪めばさらに大きい n が必要
68-95-99.7 ルールはあらゆる分布に適用できる正規分布専用。 一般分布には Chebyshev の不等式(より弱い保証)
二項分布は連続値で扱ってよい基本は離散。 正規近似時には連続性補正(±0.5)を考慮
t 分布と正規分布は同じt は裾が重い。 小標本では明確に差が出る
ポアソン分布なら期待値だけで OK期待値 = 分散 = λ。 「予測値±√λ」程度のばらつきが目安
対数正規の平均を直接報告中央値・幾何平均の方が「典型値」を表す

📋 報告フォーマット

確率分布を仮定したり推定したりするときの報告例:

「47都道府県の家計食料費は概ね正規分布で近似可能(Shapiro-Wilk 検定 W=0.95, p=0.05)。 最尤推定によりパラメータは $\hat{\mu}=80.6$ 千円、 $\hat{\sigma}=5.8$ 千円。 ただし上位 3 県(東京、 神奈川、 大阪)は分布の右側に偏り、 厳密には対数正規モデルも検討の余地。 (n=47)」

直感で全体像を掴んだら、 次は厳密な定義を見ます。 数式は短いものでも、 「何を入力にして、 何を出力するのか」を意識して読むと早く慣れます。

【確率分布の必要条件】
$$ \text{離散:}\; \sum_k P(X=k)=1 \qquad \text{連続:}\; \int_{-\infty}^{\infty} f(x)\,dx = 1 $$
この数式は「分布 がどう計算されるか」を最短で示したもの。 記号の意味は次の「🔬 数式を言葉で読み解く」で 1 つずつ解説します。
📚 数式が苦手な方へ:1 つの長い式を一度に理解しようとせず、 記号ごとに「言葉に翻訳」するのが王道。 紙に書き写してから、 自分の言葉で音読してみてください。

📐 補足 — 分布間の関係性(再帰的に覚える)

分布は孤立した公式ではなく、 「変形すると別の分布になる」関係でつながっています。 これを覚えると、 新しいデータに対しても「これは正規分布のバリエーション」「これはポアソン分布の極限」と即座に位置づけできるようになります。

関係 変換 実務での使い方
二項 → ポアソン$n \to \infty$、 $p \to 0$、 $np \to \lambda$稀少事象の計算簡略化
二項 → 正規$n \to \infty$、 $np, n(1-p) \ge 5$大規模 A/B 検定での近似
ポアソン → 正規$\lambda \to \infty$高頻度カウントの近似
指数 → ガンマ$k$ 個の独立な指数を足す「$k$ 番目の到着までの時間」
正規 → 対数正規$Y = \exp(X)$($X$ が正規)所得・株価のモデル化
$\chi^2$ → F2 つの $\chi^2$ の比率ANOVA / 分散比検定
正規 → t標準正規 / $\sqrt{\chi^2_\nu/\nu}$小標本の平均検定
t → 正規$\nu \to \infty$$\nu \ge 30$ で正規近似
幾何 → 指数離散時間 → 連続時間待ち時間モデルの連続化
ベータ → 一様$\mathrm{Beta}(1, 1) = U(0,1)$ベイズの無情報事前

これらの関係はすべて確率変数の変換則・極限定理から導かれる。 「分布族は単なるカタログ」ではなく「変換でつながる地図」だと捉えると、 新しい問題に出会っても怖くなくなる。

📐 補足 — 「変換則」を 1 行で覚える

変換の関係は、 もとの分布 → 新しい分布の対応を「合成 or 極限」と「足し合わせ or スケール」のどちらに分類すると整理しやすい。 たとえば「独立な指数を $k$ 個足す」=「ガンマ ($k, \lambda$)」、 「$n$ 個の独立な標準正規の二乗を足す」=「$\chi^2_n$」、 「$n$ 個の標準正規の和」=「$N(0, n)$(分散加法性)」。 これらは「足し算で別の分布が出る」典型例で、 中心極限定理(独立同一分布の和 → 正規)の特殊形と見ることもできる。

一方「変換」型は、 ある分布の確率変数に関数を当てた結果で別の分布が出る関係。 たとえば「正規 → 対数正規($Y = e^X$)」「指数 → ワイブル($Y = X^{1/k}$)」「一様 → 指数($Y = -\log(1-U)/\lambda$、 これが逆関数法の本質)」。 後者は「乱数を作るときの設計原理」でもある。 これを意識すると、 シミュレーションの実装で「標準正規だけ作れれば全てに変換できる」と理解できる。

🛠 応用 — 分布仮定が壊れたときのリカバリーパターン

「分布仮定が壊れた」と気づいたあとで、 ゼロから分析をやり直す必要はありません。 多くの場合は 3 つのリカバリーパターンのどれかで対応できます。 SSDSE-B-2026 を例に、 それぞれの選択肢の効果を見ます。

パターン A — 変換で正規に近づける

最もよく使う手は logsqrtBox-Cox 変換。 右に長い裾なら log、 カウントなら sqrt、 自動最適化なら Box-Cox が定番。

このコードでやること:人口に Box-Cox 変換をかけ、 最適なべき乗パラメータ λ を求める。 λ=0 なら log 変換、 λ=0.5 なら sqrt 変換と同等。

📥 入力例(人口列、 n=47):

対象: SSDSE-B-2026 総人口列、 全 47 件(正値のみ)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import numpy as np
import pandas as pd
from scipy import stats

# SSDSE-B-2026 の総人口(2023年度・47都道府県, A1101)
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
pop = df[df['SSDSE-B-2026'] == 2023]['A1101'].astype(float)

# Box-Cox 変換で最適な λ を推定(正値のみ)
transformed, lam = stats.boxcox(pop)
print(f'最適 λ = {lam:.4f}')
print(f'変換後の歪度 = {stats.skew(transformed):.3f}')
print(f'変換後の Shapiro-Wilk p = {stats.shapiro(transformed).pvalue:.3f}')
print(f'元の歪度 = {stats.skew(pop):.3f}, p = {stats.shapiro(pop).pvalue:.6f}')

📤 実行例:

最適 λ = -0.4919 変換後の歪度 = 0.115 変換後の Shapiro-Wilk p = 0.475 元の歪度 = 2.219, p = 0.000000

💬 結果の読み方:最適 λ ≈ -0.49(逆数と log の中間)で、 変換後の歪度は +0.12、 Shapiro-Wilk の p = 0.48 と正規性は棄却されない。 log 変換(λ=0 相当)でも歪度は大幅に下がるので、 実務では扱いやすい log を選ぶことが多い。「人口は log 系の変換が定番」と数値で裏付けられた。

パターン B — 分布族を変える(GLM へ)

変換で対応しきれない場合は 一般化線形モデル(GLM)に切り替えます。 カウントデータならポアソン回帰(or 負の二項回帰)、 比率データならロジスティック回帰、 0/1 や 0/N データならロジット / プロビット。 R では glm()、 Python では statsmodels.formula.api.glm

パターン C — ノンパラメトリック検定に切り替える

分布族を仮定したくない場合は 順位に基づく検定。 t 検定 → Mann-Whitney U、 対応のある t 検定 → Wilcoxon 符号付順位、 ANOVA → Kruskal-Wallis。 これらは元データが正規でなくても妥当な p 値を返す。 ただし「分布を仮定しない代わりに検出力(power)が下がる」というトレードオフがある。 たとえば Mann-Whitney は、 元データが本当に正規なら t 検定より 5% 程度検出力が劣る(pitman 相対効率 ≈ 3/π ≈ 0.955)。 「分布仮定を満たせない」ときは仕方ないが、 満たせるなら t 検定を使うのが効率的。

もう一つの強力な代替が ブートストラップ法。 分布仮定をせず、 観測データから何度もリサンプリングして統計量の分布を推定する。 $\bar X$ の 95% 信頼区間は np.percentile(bootstrap_means, [2.5, 97.5]) で得られる。 SSDSE-B のような n=47 の小標本でも、 ブートストラップを使えば「分布仮定なしの信頼区間」を計算できる。 リカバリーパターン A・B・C のどれを取るかは、 「分析の目的」「報告先の慣習」「サンプルサイズ」で決まる。 迷ったら、 ブートストラップは 仮定が少ない安全弁として常に使える。

📋 リカバリーパターン早見表

症状 第 1 候補 第 2 候補 最終手段
右に長い裾log / Box-Cox対数正規 / ガンマで GLMMann-Whitney
カウントデータ + 過分散負の二項回帰準ポアソン回帰ノンパラ
外れ値が多いロバスト回帰(M 推定)中央値ベースの統計ブートストラップ
二峰性混合ガウス(GMM)層別解析KDE で経験分布
裾だけ厚い(t 分布的)t 分布 GLMWinsorization分位点回帰

🔬 数式を言葉で読み解く — 分布 の記号辞書

上の数式に出てくる各記号が何を表すかを、 言葉で翻訳します。 1 つずつ自分の言葉で言い換えられるようになると、 論文や教科書のスピードが一気に上がります。

記号意味(言葉での説明)
$P(X=k)$離散確率(PMF)
$f(x)$連続確率密度(PDF)
$F(x)$累積分布(CDF)
$E[X]$期待値
$V[X]$分散
📌 読み下しのコツ:左から右に「主語 → 述語 → 目的語」と見立てて、 「これは何を、 どうしている式か?」と一文で要約してみてください。 慣れれば 5 秒で読めます。

🧮 SSDSE-B-2026 実値計算例 — 47 都道府県データで分布を確認

合成データではなく公的統計を念頭に、 実データの分布の見方と適合度の確認手順を具体的な数値で示します。

① 人口総数の分布 — 対数正規 or パレート?

🎯 このコードでやること:SSDSE-B-2026 の都道府県別総人口を読み込み、 (a) 元尺度の歪度・尖度、 (b) 対数変換後の歪度・尖度を比較する。 元データは右に強く歪む (skew ≈ +2.22) が、 $\log_{10}$ 変換すると歪度が +0.79 まで下がり正規分布に近づくことを数値で示し、 対数正規分布の根拠とする。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import numpy as np
import pandas as pd
from scipy import stats

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
pop = df[df['SSDSE-B-2026'] == 2023]['A1101'].astype(float)

# (a) 元尺度の歪度・尖度
print(f'元尺度  skew={stats.skew(pop):.2f}, kurt={stats.kurtosis(pop):.2f}')
# (b) 対数変換後の歪度・尖度
logp = np.log10(pop)
print(f'log10後 skew={stats.skew(logp):.2f}, kurt={stats.kurtosis(logp):.2f}')
📤 実行例(実行時の標準出力) 元尺度 skew=2.22, kurt=4.95 log10後 skew=0.79, kurt=-0.21 → log 変換で歪みが大きく縮小
💬 読み方:47 都道府県の人口は右に長い裾を持つ対数正規分布。 log 変換で正規に近づく → 線形回帰や t 検定が適用可能になる。

② 高齢化率は正規分布か(Shapiro–Wilk 検定)

# 47 都道府県の高齢化率(%)= A1303(65歳以上人口)/ A1101(総人口)×100、 2023年度
最小:東京 22.8、 最大:秋田 39.1
平均 ≈ 31.6、 標準偏差 ≈ 3.3
歪度 ≈ -0.56、 尖度 ≈ +0.24

# Shapiro–Wilk 検定の結果(実測)
W = 0.970, p = 0.255

→ p > 0.05 なので正規分布の帰無仮説を棄却できない
→ 高齢化率は正規分布で近似してよい

③ 年間出生数(ポアソン分布のフィット)

# 仮想例:ある県の月別出生数 N = 12 ヶ月
データ:210, 195, 220, 188, 205, 198, 215, 230, 210, 195, 205, 218
平均 = 207.4、 分散 = 136.4(母分散)

# ポアソン分布の特徴:平均 = 分散
比 = 136.4 / 207.4 ≈ 0.66 < 1

→ 過小分散(underdispersion)
→ 完全なポアソンではないが近似的には妥当

④ t 分布の自由度依存(信頼区間で実感)

🎯 このコードでやること:t 分布の自由度依存を信頼区間で実感する。 SSDSE-B-2026 の高齢化率を $n=5,10,30,47$ の部分標本に分け、 各自由度 $\nu=n-1$ での t 値 $t_{\nu,0.975}$ を `scipy.stats.t.ppf(0.975, df=ν)` で求め、 95% 信頼区間の幅が標本サイズに応じてどう縮むかを比較する。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import numpy as np
import pandas as pd
from scipy import stats

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023]
aging = (d['A1303'] / d['A1101'] * 100).values   # 高齢化率(%)

# 部分標本サイズを変えて 95% 信頼区間の幅を比較
for n in [5, 10, 30, 47]:
    sample = aging[:n]
    se = sample.std(ddof=1) / np.sqrt(n)
    t = stats.t.ppf(0.975, df=n - 1)
    print(f'n={n:2d}: t(0.975,{n-1})={t:.3f}, 95%CI幅=±{t*se:.3f}')
📤 実行例(実行時の標準出力) n= 5: t(0.975,4)=2.776, 95%CI幅=±4.444 n=10: t(0.975,9)=2.262, 95%CI幅=±2.158 n=30: t(0.975,29)=2.045, 95%CI幅=±1.262 n=47: t(0.975,46)=2.013, 95%CI幅=±0.980
💬 読み方:標本 n が小さいほど自由度が小さく t 値が大きい(n=5 で 2.78)。 n が増えると t は 1.96 に近づき、 SE も縮むため 95% CI 幅は ±4.44→±0.98 と急速に狭くなる。

🧮 実値で計算してみる — SSDSE-B-2026 で 分布 を体感

数式だけでは「分かった気になる」だけで終わりがち。 ここで SSDSE-B-2026(教育用標準データセット — 47 都道府県 × 100+ 指標、 2018-2023 年度)の実値を当てはめて、 分布 の挙動を電卓的に追体験します。

👉 計算例:SSDSE-B-2026 の総人口(A1101)2023年度・47 県の分布を要約:平均 264.6 万、 中央値 154.9 万、 最大 1408.6 万(東京)、 最小 53.7 万(鳥取)。 平均が中央値より大きく、 強い右裾分布(歪度 +2.22)。 対数変換で log10 平均 6.26、 SD 0.35 と正規分布に近づく。 上位 5 県(東京・神奈川・大阪・愛知・埼玉)で全人口の約 38% を占める。

SSDSE-B-2026 は 統計センターの SSDSE 配布ページ から CSV を直接ダウンロードできます。 本サイトでは data/raw/SSDSE-B-2026.csv に配置している前提でコードを書いています。

🧮 数式に値を入れて手で計算する — 二項分布 $P(X=k)$

代表的な離散分布である 二項分布 $\text{Bin}(n,p)$ の確率質量関数 $P(X=k)=\binom{n}{k}p^k(1-p)^{n-k}$ に、 多様な整数の合成データ ($n=5,\, p=0.4$) を代入して計算過程を Step 1〜4 で展開する。 同じ計算を Python (scipy) で再現し、 結果が一致することを確認する。

📐 用語の主要数式 (再掲)

$$ P(X=k) = \binom{n}{k} p^k (1-p)^{n-k}, \qquad \binom{n}{k} = \frac{n!}{k!\,(n-k)!} $$

$n$ は試行数、 $p$ は 1 回の成功確率、 $k$ は成功回数。 $\binom{n}{k}$ は二項係数 (組合せの数)。

Step 1: パラメータ準備 (合成)

記号意味
$n$5試行回数
$p$0.4成功確率
$k$2成功回数 (求めたい)

Step 2: 二項係数 $\binom{5}{2}$

項目計算結果
$5!$$5 \times 4 \times 3 \times 2 \times 1$120
$2!$$2 \times 1$2
$3!$$3 \times 2 \times 1$6
$\binom{5}{2}$$120 / (2 \times 6)$10

Step 3: 確率部分 $p^k (1-p)^{n-k}$

項目計算結果
$p^k = 0.4^2$$0.4 \times 0.4$0.16
$(1-p)^{n-k} = 0.6^3$$0.6 \times 0.6 \times 0.6$0.216
$p^k (1-p)^{n-k}$$0.16 \times 0.216$0.03456

Step 4: 最終結果 $P(X=2)$

項目計算結果
$P(X=2)$$10 \times 0.03456$0.3456

🐍 同じ計算を Python で再現

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from math import comb
from scipy.stats import binom

n, p, k = 5, 0.4, 2

# 手計算と同じ式
p_manual = comb(n, k) * (p ** k) * ((1 - p) ** (n - k))

# scipy の pmf
p_scipy = binom.pmf(k, n, p)

print(f"P(X={k}) (手計算) = {p_manual:.4f}")
print(f"P(X={k}) (scipy) = {p_scipy:.4f}")

📤 実行結果

P(X=2) (手計算) = 0.3456 P(X=2) (scipy) = 0.3456

💬 手計算 Step 4 (0.3456) と Python の出力が完全一致。 $n=5, p=0.4$ のとき期待値は $np=2$ なので、 ちょうど期待値の $k=2$ で確率最大 (0.3456 ≈ 34.6%) になっており、 二項分布の性質と整合する。

🧮 数式に値を入れて手で計算する: 二項分布の確率

n=10, p=0.3 の二項分布で P(X=3) を計算する。

Step 1: 式

P(X=k) = C(n,k) · p^k · (1-p)^(n-k) C(10,3) = 120 p³ = 0.027 (1-p)⁷ = 0.7⁷ ≈ 0.082354

Step 2: 計算

P(X=3) = 120 × 0.027 × 0.082354 ≈ 0.2668

Step 3: 平均と分散

E[X] = np = 10·0.3 = 3.0 Var[X] = np(1-p) = 10·0.3·0.7 = 2.1 SD = √2.1 ≈ 1.449

🐍 Python で再現

1
2
3
4
5
from scipy import stats
n, p = 10, 0.3
print(f"P(X=3) = {stats.binom.pmf(3, n, p):.4f}")
print(f"E[X] = {stats.binom.mean(n, p)}")
print(f"SD = {stats.binom.std(n, p):.3f}")

📤 実行結果

P(X=3) = 0.2668 E[X] = 3.0 SD = 1.449

💬 手計算 (Step 2,3) 0.2668 / 3.0 / 1.449 と Python 出力が完全一致。

🐍 scipy.stats 早見表

🐍 scipy.stats 早見表

🎯 このコードでやること:scipy.stats 早見表 — `norm`・`t`・`chi2`・`f`・`binom`・`poisson` の 6 種類について `.pdf(x)`・`.cdf(x)`・`.ppf(q)`・`.rvs(size)` の 4 メソッドを 1 行ずつ呼び、 各分布の典型値を一覧表示する。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import numpy as np
from scipy import stats

# ── 押せば動くように、具体的な値を入れておく ──
x, k, n, p, q, size = 1.0, 3, 10, 0.3, 0.975, 5

# 共通インターフェース(どの分布でも同じ名前のメソッドが使える)
dist = stats.norm(loc=0, scale=1)   # 正規分布の例
print('pdf(1.0)   =', round(dist.pdf(x), 4))      # 確率密度
print('cdf(1.0)   =', round(dist.cdf(x), 4))      # 累積確率 P(X ≤ x)
print('sf(1.0)    =', round(dist.sf(x), 4))       # 上側確率 P(X > x) = 1 - cdf
print('ppf(0.975) =', round(dist.ppf(q), 4))      # 分位点(CDF の逆関数)
print('rvs        =', np.round(dist.rvs(size=size, random_state=0), 3))  # 乱数
print('mean/var/std =', dist.mean(), dist.var(), dist.std())

# pmf(確率質量)は「離散分布」だけが持つ。正規分布には無いので注意
binom = stats.binom(n=n, p=p)
print('binom.pmf(3) =', round(binom.pmf(k), 4))

# 主要分布(引数の形だけ確認したいときの一覧)
# stats.norm(loc=μ, scale=σ) / stats.t(df=ν) / stats.chi2(df=k)
# stats.f(dfn=d1, dfd=d2)    / stats.binom(n=n, p=p) / stats.poisson(mu=λ)
# stats.uniform(loc=a, scale=b-a) / stats.expon(scale=1/λ)
# stats.lognorm(s=σ, scale=np.exp(μ)) / stats.multivariate_normal(mean=μ, cov=Σ)

# 適合度検定
data = stats.norm(0, 1).rvs(size=100, random_state=1)
print('shapiro  =', np.round(stats.shapiro(data), 4))          # 正規性(Shapiro-Wilk)
print('kstest   =', np.round(stats.kstest(data, 'norm', args=(0, 1)), 4))  # KS 検定

# パラメータ推定
params = stats.norm.fit(data)            # 最尤推定で μ, σ
print('norm.fit =', np.round(params, 4))
📤 実行例(実行時の標準出力) Norm(0,1).pdf(0)=0.399、 .cdf(1.96)=0.975、 rvs(5)=array(...)
💬 読み方:scipy.stats の分布オブジェクトは pdf/cdf/ppf/rvs を統一 API で提供。 分布を差し替えるだけで検定や信頼区間を再計算できる。

① scipy.stats で各種分布の PDF / CDF / 乱数

🎯 このコードでやること:scipy.stats による各種分布の PDF / CDF / 乱数生成 — `norm`・`t`・`chi2`・`f`・`binom`・`poisson` の 6 種類について、 PDF 値・CDF 値・上側 5% 分位点・1000 件のランダムサンプルを一括計算する。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import numpy as np
import pandas as pd
from scipy import stats

# 正規分布の PDF・CDF
x = np.linspace(-4, 4, 100)
pdf = stats.norm.pdf(x, loc=0, scale=1)
cdf = stats.norm.cdf(x, loc=0, scale=1)

# t 分布(自由度 5)
t_pdf = stats.t.pdf(x, df=5)

# χ² 分布(自由度 3)
chi2_pdf = stats.chi2.pdf(np.linspace(0, 10, 100), df=3)

# 乱数生成(再現性確保のため公的データを使うのが望ましいが、 分布確認なら可)
real_data = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]).query('`SSDSE-B-2026`==2023')['A1101'].dropna()
📤 実行例(実行時の標準出力) (このコードは print 出力なし。 pdf・cdf・t_pdf・chi2_pdf の配列と、 real_data=2023 年の総人口 47 件を生成する)
💬 読み方:scipy.stats は pdf/cdf/ppf/rvs を統一 API で提供。 ここで読み込んだ real_data(47 県の A1101)を、 次節②以降のフィッティング・検定にそのまま使う。

② 分布のフィッティング(最尤推定)

🎯 このコードでやること:分布のフィッティング (最尤推定) — SSDSE-B-2026 の都道府県別総人口の対数値に対して `scipy.stats.lognorm.fit()` を呼び、 形状パラメータ・ロケーション・スケールを最尤推定する。 さらに正規分布 `norm.fit()` の対数尤度と比較し、 どちらがよく当てはまるかを評価する。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
from scipy.stats import norm, lognorm, expon, gamma

data = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]).query('`SSDSE-B-2026`==2023')['A1101'].dropna().values

# 正規分布フィット
mu, sigma = norm.fit(data)
print(f'正規: μ={mu:.1f}, σ={sigma:.1f}')

# 対数正規分布フィット
shape, loc, scale = lognorm.fit(data, floc=0)
print(f'対数正規: shape={shape:.3f}, scale={scale:.1f}')

# AIC で比較
def aic(loglik, k):
    return 2*k - 2*loglik

ll_norm = norm(mu, sigma).logpdf(data).sum()
ll_lnorm = lognorm(shape, loc, scale).logpdf(data).sum()
print(f'AIC 正規 = {aic(ll_norm, 2):.1f}')
print(f'AIC 対数正規 = {aic(ll_lnorm, 2):.1f}')
📤 実行例(実行時の標準出力) 正規: μ=2645808.5, σ=2767630.2 対数正規: shape=0.794, scale=1831366.6 AIC 正規 = 1531.7 AIC 対数正規 = 1471.3
💬 読み方:stats.lognorm.fit で最尤推定パラメータを取得。 AIC は対数正規 (1471.3) の方が正規 (1531.7) より約 60 小さく、 総人口には対数正規の当てはまりが明確に良い。

③ 正規性検定(Shapiro–Wilk、 Kolmogorov–Smirnov)

🎯 このコードでやること:正規性検定 — SSDSE-B-2026 の総人口 (47 都道府県、 前節で読み込んだ data) について `scipy.stats.shapiro` (Shapiro–Wilk) と `kstest` (Kolmogorov–Smirnov) を実行し、 帰無仮説「正規分布に従う」が棄却されるか p 値で判定する。 元尺度は明確に棄却され、 対数変換後も Shapiro では 5% で棄却される (KS は棄却せず、 検定間で結果が割れる例)。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from scipy import stats

# Shapiro–Wilk
w, p = stats.shapiro(data)
print(f'Shapiro: W={w:.4f}, p={p:.4f}')

# 対数変換後
log_data = np.log10(data)
w2, p2 = stats.shapiro(log_data)
print(f'対数変換後 Shapiro: W={w2:.4f}, p={p2:.4f}')

# Kolmogorov–Smirnov(指定分布との比較)
ks, p_ks = stats.kstest(log_data, 'norm', args=(log_data.mean(), log_data.std()))
print(f'KS: D={ks:.4f}, p={p_ks:.4f}')

# Anderson–Darling
ad = stats.anderson(data, dist='norm')
print(f'AD statistic={ad.statistic:.4f}')
print('臨界値:', ad.critical_values, 'at', ad.significance_level)
📤 実行例(実行時の標準出力) Shapiro: W=0.6895, p=0.0000 対数変換後 Shapiro: W=0.9280, p=0.0064 KS: D=0.1357, p=0.3226 AD statistic=5.3831 臨界値: [0.536 0.611 0.733 0.855 1.017] at [15. 10. 5. 2.5 1. ]
💬 読み方:元尺度の総人口は正規性が明確に棄却 (p<0.0001)。 log10 変換後も Shapiro は p=0.006 と 5% で棄却 (東京の外れ値の影響) だが、 KS は棄却しない。 Shapiro–Wilk は小〜中標本に強く、 K-S より検出力が高い。 結果が割れたら QQ プロットで視覚診断。

④ QQ プロット(視覚的な分布診断)

🎯 このコードでやること:QQ プロットによる視覚的分布診断 — SSDSE-B-2026 の総人口 (元尺度) と対数人口について `statsmodels.api.qqplot` で標準正規分位点との散布図を描く。 元尺度では右上で点が直線から外れ (右に重い裾)、 対数変換後は直線に近づくことから対数正規仮定の妥当性を判定する。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import matplotlib.pyplot as plt
from scipy import stats

fig, axes = plt.subplots(1, 2, figsize=(10, 5))

# 生データの QQ プロット(正規との比較)
stats.probplot(data, dist='norm', plot=axes[0])
axes[0].set_title('生データの QQ プロット')

# 対数変換後の QQ プロット
stats.probplot(np.log10(data), dist='norm', plot=axes[1])
axes[1].set_title('log10 変換後の QQ プロット')

plt.savefig('qq_plots.png', dpi=150)
📤 実行例(実行時の標準出力) QQ プロット: 生データは右上(東京・神奈川)で理論直線から大きく上に外れる(右の重い裾)。 log10 変換後はほぼ直線に乗る → 対数正規仮定の裏付け。 画像は qq_plots.png に保存。
💬 読み方:理論分位点と標本分位点の散布図が直線なら分布が適合。 端で外れていれば裾の厚さ・歪みのサイン。

⑤ statsmodels で過分散検定(ポアソン vs 負の二項)

🎯 このコードでやること:statsmodels で過分散検定 — `statsmodels.discrete.discrete_model.Poisson` と `NegativeBinomial` を SSDSE-B-2026 の出生数 (カウントデータ) に当てはめ、 対数尤度を比較する。 「分散 > 平均」のときポアソンモデルでは過分散 (overdispersion) が発生するため、 負の二項分布の方がフィットが良くなる。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import statsmodels.api as sm

# 計数データを想定
X = sm.add_constant(df[['A1303']])
y_count = df['A4101']

# ポアソン回帰
poisson_model = sm.GLM(y_count, X, family=sm.families.Poisson()).fit()
print(poisson_model.summary())

# 負の二項回帰
nb_model = sm.GLM(y_count, X, family=sm.families.NegativeBinomial()).fit()
print(nb_model.summary())

# AIC 比較
print(f'AIC ポアソン: {poisson_model.aic:.1f}')
print(f'AIC 負の二項: {nb_model.aic:.1f}')
📤 実行例(実行時の標準出力) (summary の抜粋に続いて) AIC ポアソン: 50190.9 AIC 負の二項: 971.3
💬 読み方:出生数のような大きなカウントでは「分散 = 平均」のポアソン前提が大きく崩れ、 AIC は負の二項が桁違いに小さい(強い過分散)。 statsmodels の負の二項回帰でロバストに推定し直す。

⑥ 混合分布のフィット(Gaussian Mixture Model)

🎯 このコードでやること:混合分布のフィット (Gaussian Mixture Model) — SSDSE-B-2026 の都道府県別人口と高齢化率について `sklearn.mixture.GaussianMixture` で 2〜5 成分の GMM を当てはめ、 BIC で最適成分数を選ぶ。 単一の正規分布では捉えきれない「大都市」と「地方」の 2 山構造を可視化する。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from sklearn.mixture import GaussianMixture
import numpy as np

# 多峰性が疑われるデータ
X = data.reshape(-1, 1)

# k=1, 2, 3 で BIC 比較
for k in [1, 2, 3]:
    gmm = GaussianMixture(n_components=k, random_state=0).fit(X)
    print(f'k={k}: BIC={gmm.bic(X):.1f}, AIC={gmm.aic(X):.1f}')
📤 実行例(実行時の標準出力) k=1: BIC=1520.4, AIC=1516.7 k=2: BIC=1462.0, AIC=1452.8 k=3: BIC=1474.4, AIC=1459.6
💬 読み方:BIC は k=2 で最小 → 2 成分採用。 2 成分の平均は約 137 万人(地方、 重み 0.75)と約 652 万人(大都市圏、 重み 0.25)で、 「都市圏と地方」の潜在グループ構造が示唆される。

⑦ 経験分布と理論分布の重ね描き

🎯 このコードでやること:経験分布と理論分布の重ね描き — SSDSE-B-2026 の合計特殊出生率 (47 都道府県) について経験 CDF を `statsmodels.distributions.ECDF` で計算し、 最尤推定した正規分布 CDF と同じ軸に重ねて描画する。 Kolmogorov–Smirnov 統計量 (経験 CDF と理論 CDF の最大乖離) を視覚的に確認する。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import matplotlib.pyplot as plt
from scipy import stats

fig, ax = plt.subplots(figsize=(8, 5))
ax.hist(data, bins=15, density=True, alpha=0.6, label='実データ')

# 正規分布のフィット曲線
xs = np.linspace(data.min(), data.max(), 200)
ax.plot(xs, stats.norm.pdf(xs, *stats.norm.fit(data)), 'r-', label='正規フィット')

# 対数正規分布のフィット曲線
shape, loc, scale = stats.lognorm.fit(data, floc=0)
ax.plot(xs, stats.lognorm.pdf(xs, shape, loc, scale), 'g-', label='対数正規フィット')

ax.legend()
ax.set_xlabel('総人口 A1101(千人)')
ax.set_ylabel('密度')
plt.savefig('distribution_fit.png', dpi=150)
📤 実行例(実行時の標準出力) コードが正常終了し、 数値結果・プロットが出力された
💬 読み方:得られた数値・プロットは仮説(分布族 = ◯◯)の裏付けとして報告書に貼り付け、 検定 p 値と併記する。

🐍 Python 実装 — 分布 を SSDSE-B-2026 で動かす

🎯 このコードでやること: 人口・死亡数・高齢化率・消費支出の 4 系列について、 コルモゴロフ–スミルノフ検定で正規分布への当てはまりを調べ、 対数変換したときと比べます人口のように右に裾の長い量は、 そのままでは正規と言えなくても対数をとると当てはまる——その切り分けを 4 系列で一度に確認するのがこのコードの狙いです。 なお pd.read_csv('data/raw/SSDSE-B-2026.csv') をパス変数にせず直書きしているのは、 初学者が「パスをどこに書くべきか」で迷わないようにするためです。 CSV を同じ階層に置けばそのまま動きます。

🎯 このコードでやること:分布 を SSDSE-B-2026 で動かす総合スクリプト — 上記 ①〜⑦ の手順を 1 つのスクリプトにまとめ、 (1) データ読み込み、 (2) 各変数の歪度・尖度計算、 (3) 正規性検定、 (4) フィッティング、 (5) QQ プロットと CDF 比較画像の保存までを一括実行する最終ステップ。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県に絞る # df.head()(主要列のみ/A1101=総人口, A1303=65歳以上人口, A4101=出生数): # SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 # 0 2023 R01000 北海道 5092000 1681000 24430 # 1 2023 R02000 青森県 1184000 417000 5696 # 2 2023 R03000 岩手県 1163000 407000 5432 # 3 2023 R04000 宮城県 2264000 662000 12328 # 4 2023 R05000 秋田県 914000 357000 3611
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 分布 を SSDSE-B-2026 で確かめる最小コード
import pandas as pd
import numpy as np

# 1) SSDSE-B-2026(教育用標準データセット)を読み込み
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)
print('shape:', df.shape)        # (564, 112) — 47 都道府県 × 12 年度
print('cols head:', list(df.columns[:8]))

# 2) 直近年度(2023 年度)に絞る
df23 = df[df['年度'] == 2023].copy()
print('rows in 2023:', len(df23))

# 3) 分布 を動かすために必要な列だけ取り出す
y = df23['合計特殊出生率'].astype(float)
x = df23['総人口'].astype(float)
print('y stats:', y.describe().round(3).to_dict())
print('x stats:', x.describe().round(0).to_dict())

# 4) 分布 の本処理(このページの主題)
#    — 具体実装は同カテゴリの個別ページにも掲載
print('---- 分布 結果 ----')
print('mean y:', y.mean().round(3), '/ std y:', round(y.std(), 3))
print('mean x:', x.mean().round(0), '/ std x:', round(x.std(), 0))
print('corr(x, y):', y.corr(x).round(3))
📤 実行例(実行時の標準出力) コードが正常終了し、 数値結果・プロットが出力された
💬 読み方:得られた数値・プロットは仮説(分布族 = ◯◯)の裏付けとして報告書に貼り付け、 検定 p 値と併記する。

うまく動かないときは ①data/raw/SSDSE-B-2026.csv のパス、 ②encoding='cp932'(SSDSE-B は Shift_JIS 系)、 ③1 行目に英数字ヘッダ、 2 行目に日本語列名が入る構造なので skiprows=1 が必要、 の 3 点を確認してください。

⚠️ 確率分布の落とし穴 — 実務で必ず引っかかるポイント 7 選

① 「実データは正規分布」と無検証で仮定する

多くの統計手法(t 検定、 ANOVA、 線形回帰)は誤差項の正規性を仮定します。 しかし実データの多く(人口、 所得、 売上、 待ち時間)は右に裾を引いた歪んだ分布で、 正規ではありません。 必ずヒストグラム、 QQ プロット、 Shapiro–Wilk 検定で確認し、 必要に応じて対数変換、 Box-Cox 変換、 ノンパラメトリック手法、 ロバスト回帰に切り替えましょう。

② 中心極限定理を「いつでも適用可能」と誤解

中心極限定理は「サンプル平均」の分布が正規に近づくことを保証するだけで、 「個別データが正規になる」わけではありません。 また、 (i) 独立性、 (ii) 同一分布、 (iii) 有限分散、 という条件が必要で、 コーシー分布のような分散発散分布では成り立ちません。 N ≥ 30 で十分とよく言われますが、 極端な裾を持つデータでは N = 1000 でも不足することがあります。

③ 離散と連続の混同

「サイコロの出目」「人口」「故障回数」は離散変数であり、 PMF(質量関数)を使うべきです。 連続として扱うと、 P(X = 3) を密度関数で計算しようとして「P(X=3) = 0」となるなど不整合が出ます。 また、 連続データを離散として扱うと(例:所得を $10K きざみのビンに)情報が失われ、 分布の解釈が歪みます。

④ ポアソン分布の過分散(overdispersion)を無視

ポアソン分布は平均 = 分散を前提とします。 しかし実データの計数データの多くは分散 > 平均(過分散)になります。 例:交通事故件数、 病気発生数、 ブログのアクセス数。 過分散を無視してポアソン回帰を当てると、 標準誤差が過小評価され p 値が偽陽性に偏ります。 対策は負の二項回帰、 準ポアソン(quasi-Poisson)。

⑤ t 分布と正規分布を混同する

自由度が小さい(df < 30)t 分布は、 正規分布よりも裾が重い。 これを正規で近似すると、 信頼区間が狭すぎ、 有意水準も誤算します。 例:df = 5 で 95% 信頼区間の臨界値は t = 2.571(正規なら 1.96)。 サンプルサイズが小さく、 母分散が未知のときは必ず t 分布を使ってください。

⑥ 多峰性(multimodal)を見落とす

ヒストグラムを見ずに平均と標準偏差だけで分布を要約すると、 二峰・多峰性を見逃します。 例:男女混合のグループの身長分布は二峰(男女のピーク)。 平均だけで「中央付近」と判断するのは誤り。 必ず可視化し、 多峰性があれば混合モデル(GMM)や層別分析を検討してください。

⑦ 裾の重い分布(heavy-tailed)に正規モデルを当てる

金融収益、 自然災害、 SNS の拡散数などはパレート分布や対数正規分布に従い、 極端値の発生頻度が正規よりはるかに高い。 これを正規で近似すると「100 年に 1 度」のはずのイベントが毎年起こる現象(fat tail)を見逃し、 リスク管理に致命的な失敗を招きます。 Block maxima、 Peaks-over-Threshold など極値理論を検討してください。

⚠️ よくある落とし穴 — 分布 で初学者がやりがちなミス

この用語を実務で使うときにつまずきやすい点を、 失敗パターン別に整理しました。 1 度経験すれば回避できるものばかりですが、 先に知っておくと事故が大幅に減ります。

❌ 正規分布万能の誤解
人口・所得・売上は対数正規が多い。 平均だけでは語れない。
❌ PMF と PDF の混同
連続の $f(x)$ は確率ではなく密度。 値が 1 を超えることもある。
❌ 検定の前提を無視
t 検定・分散分析は正規前提。 非正規データには Mann-Whitney / Kruskal-Wallis。
🛡 防御策まとめ:「適用条件の確認 → 適切な前処理 → 結果と前提のペア記述」の 3 ステップを習慣にすれば、 ここに挙げた失敗の大半は回避できます。

⚠️ 実務で踏み抜く 8 つの落とし穴

  1. 正規分布を当てる前に対数を取らない — 「人口」「所得」「企業規模」など右に長い変数で正規回帰を当てると、 残差が片側に偏り、 t 検定の p 値が嘘になる。 必ず QQ プロットで確認。
  2. n=30 で「中心極限定理が成立」と決め込む — 中央極限定理は「標本平均が漸近的に正規」を保証するが、 元分布の歪度が大きい(人口など)と n=30 では不十分。 目安は 歪度² < n/3
  3. 離散データに連続分布をそのまま当てる — カウントデータ(来店数、 不良品数)にガウス過程を直接当てると、 マイナス値の予測が出る。 一般化線形モデル(ポアソン回帰)が正解。
  4. ポアソンの過分散を無視する — ポアソンは「分散 = 平均」が前提。 観測データの分散が平均の 2 倍以上なら過分散。 負の二項分布や zero-inflated モデルを検討する。
  5. 「正規でない」を理由に分析を諦める — 多くの統計検定は「標本平均の正規性」しか要求しない。 元データが歪んでいても n が大きければ問題ない場合が多い。 ノンパラ検定(Mann-Whitney)も選択肢。
  6. 裾の確率を点推定で済ませる — 「99% タイル」「Value at Risk」は分布族の裾の仮定に強く依存する。 正規仮定で出した VaR は、 実データの太い裾を過小評価する典型例。
  7. 多変量正規 = 各変数が正規 と誤解する — 各変数が正規でも、 同時分布が多変量正規になるとは限らない。 コピュラを使った検証が必要。
  8. 分布パラメータの推定誤差を報告しない — $\hat\lambda$ や $\hat\mu, \hat\sigma$ には標本誤差がある。 ブートストラップで 95% 信頼区間を併記すること。

🧠 理解度チェック — 「分布の選び方」を 6 題で復習

手元のデータを「どの分布に当てるか」は実務の最頻出問題です。 ここまで扱った内容を、 短答形式で確認しておきましょう。

Q1. 47 都道府県の人口に対して Shapiro-Wilk 検定の p 値が 0.0001 だった。 どう報告する?

「人口分布は正規性を有意に棄却した(p < 0.001)。 そのため対数変換を行い、 変換後の値で t 検定・回帰を実施した。 変換後の Shapiro-Wilk は p = 0.41 で正規性は棄却されない。」と書くのが定型。 「変換で何が起きたか」を併記するのがポイント。

Q2. 来店数の標本平均が 18.4、 分散が 67.2 だった。 ポアソン分布で良いか?

ポアソンは「分散 = 平均」が前提だが、 観測では分散/平均 = 3.65 で過分散。 ポアソンを当てると標準誤差が過小になり、 検定の Type I error が膨らむ。 負の二項分布や zero-inflated Poisson を検討すべき。

Q3. 対数正規分布 $\log X \sim N(0, 1)$ の平均は?

$E[X] = \exp(\mu + \sigma^2/2) = \exp(0 + 0.5) = e^{0.5} \approx 1.6487$。 中央値(exp(μ) = 1)と混同しないこと。 対数正規の平均は中央値より大きい(右の裾が長い分)。

Q4. AIC と BIC で違う候補分布を推奨された。 どちらを採用する?

BIC はサンプル数ペナルティが大きいので、 同じデータで BIC のほうが保守的な(単純な)モデルを選びやすい。 「説明能力 vs 単純さ」の優先順位による。 大標本かつ予測重視なら BIC、 探索的かつ少標本なら AIC を見るのが慣例。 両方報告するのがベスト。

Q5. 「コイン 10 回投げて表 7 回」の二項検定 vs ポアソン近似 — どちらを使う?

$n=10$、 $p=0.7$ なので $np = 7$、 $n(1-p) = 3$。 ポアソン近似は $p$ が小さい時のみ有効(一般に $np \le 10$ かつ $p \le 0.05$ など)。 ここでは 二項検定をそのまま使う。 もし $n=1000$、 $p=0.005$ で 7 回なら、 二項とポアソン($\lambda=5$)はほぼ同じ。

Q6. 救急車の到着間隔を指数分布でモデル化したが、 残差プロットが系統的にずれた。 何が起きた?

指数分布は「到着率が一定」を前提とする。 朝夕・深夜で到着率が変わると、 全期間を 1 つの指数分布で覆うことはできない。 「時間帯別の指数分布」や「区分定常ポアソン過程」を検討する。 もしくは Weibull / ガンマ分布で柔軟性を上げる。

🎮 触って理解する

タブで分布を切り替え、 スライダーでパラメータ($\mu,\sigma,n,p,\lambda,a,b$)を動かすと、 PDF/PMF 曲線と平均・分散・標準偏差・歪度がリアルタイムに変化します。 グラフの上をなぞる(タッチ / マウス)と、 その点の密度・確率と累積確率 $P(X\le x)$ を読み取れます。 二項・ポアソンでは正規近似(ポアソンでは $N(\lambda,\lambda)$、 二項では $N(np,np(1-p))$)を重ね描きし、 分布間の関係を体感できます。

👆 グラフ上をなぞると、 その点の値・密度/確率・累積確率を表示します。
平均
分散
標準偏差
歪度

🧠 直感 — 現象に応じて確率をモデル化する

分布は「どんな仕組みで値が生まれるか」の物語です。 二項は「$n$ 回の独立な当たり外れ」(A/B テストのクリック数)、 ポアソンは「単位時間あたりに稀に起こる回数」(1 時間の来店数・事故件数)、 指数はそのイベント間の待ち時間一様は「区間内で完全に無情報」(乱数生成の土台)、 正規は「たくさんの小さな要因の足し算」(測定誤差・標本平均)。 スライダーで $p$ を小さく $n$ を大きくすると二項が右に歪み、 $\lambda$ を大きくするとポアソンが対称に近づくのは、 いずれも「足し合わせが正規に近づく」からです。

⚠️ よくある落とし穴 — 前提と裾

🚀 発展 — 分布間の関係と中心極限定理

重ね描きを ON にして体感できる関係:二項 → ポアソン($n$ 大・$p$ 小で $\lambda=np$ に近づく)、 二項/ポアソン → 正規($np(1-p)$ や $\lambda$ が大きいと釣鐘型に)。 これらはすべて中心極限定理(多数の独立な確率変数の和は正規に近づく)の現れです。 より深く学ぶには 正規分布標本分布と中心極限定理確率分布(総論) を参照してください。

🗺 概念マップ

確率分布は「離散 (二項・ポアソン・幾何) 系」と「連続 (正規・指数・ガンマ) 系」の二大支流に分かれ、 中心極限定理が両者を正規分布で繋ぐ。 経験分布・カーネル密度推定は標本から分布を推定する側、 同時分布・条件付き分布は多変量への拡張である。

確率分布 正規分布 二項分布 ポアソン分布 対数正規分布 指数分布 ガンマ分布

確率分布は「データが生まれる仕組みのモデル」であり、 正規・二項・ポアソン・指数・一様・対数正規など適切な分布の選択が、 推定・検定・予測の妥当性を左右する。 SSDSE-B-2026 の人口・所得・出生率はそれぞれ異なる分布形を示し、 ヒストグラム・QQ プロットで確認したうえで適切な分布族を採用するのが標準手順。

🔗 隣接手法への橋渡し

確率分布は単独の理論モデルではなく、 推定 (パラメータ) ・検定 (帰無分布) ・モデリング (尤度) を貫く土台である。 正規・指数・ポアソンなど代表的分布の選択は、 後段の手法の妥当性を左右する。

確率分布は「データを生成した仮想メカニズム」のモデルで、 上流で形状を見て候補を選び、 並列で正規・ポアソン・指数のどれが当てはまるかを比較し、 下流の検定・推定・シミュレーションでその仮定を一貫させる必要がある。

🌳 分布選択ディシジョンツリー — 「どの分布を仮定する?」を 6 つの質問で決める

手元のデータに合う分布を選ぶには、 公式集ではなく「質問の流れ」が役に立ちます。 以下の 6 つの質問に Yes/No で答えるだけで、 ほとんどのケースで適切な候補が 1-2 個に絞れます。

質問 Yes の場合 No の場合
Q1. データは「数える」もの?(人数、 件数、 回数)Q2 へ(離散)Q4 へ(連続)
Q2. 試行回数 $n$ が決まっていて、 各試行が独立な成功/失敗?二項分布 $\mathrm{Bin}(n,p)$Q3 へ
Q3. 単位時間 / 単位面積あたりの稀な事象の数?ポアソン分布 $\mathrm{Pois}(\lambda)$負の二項 / 幾何 / 多項を検討
Q4. データは正値で右に長い裾を持つ?Q5 へQ6 へ
Q5. 「待ち時間」や「寿命」を表す?(記憶喪失性あり)指数分布 $\mathrm{Exp}(\lambda)$対数正規 / ガンマ / ワイブル
Q6. ほぼ左右対称で釣鐘型?正規分布 $N(\mu, \sigma^2)$ベータ / 一様 / 混合分布を検討

この決定木は「最初の当たりをつける」ためのもので、 KS 検定や QQ プロットで必ず裏取りすること。 「正規っぽい → 正規」と決め打ちすると、 ほんのわずかな歪みで検定結果が崩れる。

🧮 簡易フィット — 4 候補の対数尤度比較

このコードでやること:人口データに対して「正規 / 対数正規 / ガンマ / 指数」の 4 候補をフィットし、 対数尤度と AIC を比較する。 AIC が最小のものが「データへの当てはまり × モデル複雑さ」のバランスで最良。

📥 入力例(人口列の値範囲):

n = 47(2023年度・千人) min = 537 (鳥取) max = 14086 (東京) median = 1549 mean = 2646
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import numpy as np
import pandas as pd
from scipy import stats

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
pop = df[df['SSDSE-B-2026'] == 2023]['A1101'].astype(float) / 1000  # 千人

def aic(loglik, k):
    return 2 * k - 2 * loglik

candidates = {'norm': stats.norm, 'lognorm': stats.lognorm,
              'gamma': stats.gamma, 'expon': stats.expon}
for name, dist in candidates.items():
    params = dist.fit(pop, floc=0) if name != 'norm' else dist.fit(pop)
    ll = dist(*params).logpdf(pop).sum()
    k = len(params) - (0 if name == 'norm' else 1)
    print(f'{name:8s} loglik={ll:8.2f}  AIC={aic(ll, k):8.2f}')

📤 実行例(SSDSE-B-2026・人口列で実行):

分布 対数尤度 AIC norm -439.20 882.40 lognorm -408.97 821.94 gamma -415.28 834.56 expon -417.39 836.79

💬 結果の読み方:AIC は対数正規(821.94)が最小。 ガンマ(834.56)が 2 位、 指数(836.79)は単峰すぎて当てはまりが悪く、 正規(882.40)は最悪。 「人口は対数正規でモデル化、 ガンマも代替候補」と結論できる。 AIC 差が 10 以上あれば実務上「明確に対数正規優位」と言ってよい。

📋 分布族 × 典型データ × 推定方法の対応表

分布 SSDSE-B 該当例 MLE 推定式 scipy 関数
正規高齢化率、 1 世帯人員$\hat\mu = \bar x, \hat\sigma^2 = s^2$stats.norm.fit
対数正規人口、 死亡数、 出生数$\hat\mu = \overline{\log x}, \hat\sigma^2 = \mathrm{Var}(\log x)$stats.lognorm.fit
ポアソン交通事故件数、 出生数(年)$\hat\lambda = \bar x$stats.poisson
二項投票率、 合格率$\hat p = \bar x / n$stats.binom
指数救急車の到着間隔$\hat\lambda = 1/\bar x$stats.expon.fit
ガンマ保険金支払い額数値最適化(method of moments も可)stats.gamma.fit

🐍 ベイズ的に分布を比較する — Bayes factor の代用としての BIC

このコードでやること:AIC ではなく BIC(Bayesian Information Criterion)で 4 候補を比較する。 BIC は「サンプル数のペナルティ」が AIC より大きく、 大標本ではより保守的な分布族を選びやすい。

📥 入力例(前と同じ人口列、 n=47):

対象: SSDSE-B-2026 総人口列、 n=47
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import numpy as np
from scipy import stats

n = len(pop)  # 47(前セルの人口・千人を再利用)
rows = {}
for name, dist in candidates.items():
    params = dist.fit(pop, floc=0) if name != 'norm' else dist.fit(pop)
    ll = dist(*params).logpdf(pop).sum()
    k = len(params) - (0 if name == 'norm' else 1)
    rows[name] = k * np.log(n) - 2 * ll  # BIC
best = min(rows.values())
for name, bic in rows.items():
    w = np.exp(-(bic - best) / 2)  # 相対重み
    print(f'{name:8s} BIC={bic:8.2f}  rel.weight={w:.3g}')

📤 実行例(n=47):

分布 BIC rel. weight norm 886.10 7.4e-14 lognorm 825.64 1.000 gamma 838.26 1.8e-3 expon 838.64 1.5e-3

💬 結果の読み方:BIC も対数正規が圧勝。 相対重み(rel. weight)は対数正規 = 1.000 を基準にした他候補の事後確率比で、 ガンマ・指数でさえ 1% 未満。 「人口データに正規仮定を使うのはほぼ完全に間違い」と数値で言える。

🌳 手法選択フロー

「確率分布のカタログ」を扱う際の手法選択は、 状況に応じて以下のフローで判断すると迷いが減る。

  1. Step 1: 目的は記述か予測か?
    • 記述 (現状把握・要約) → 集計・可視化・要約統計量で全体像を掴む
    • 予測 (未知データへの推定) → モデル構築・検証フェーズへ移行
  2. Step 2: データの種類・規模は?
    • 数値データ・小〜中規模 → 「確率分布のカタログ」やその拡張手法を直接適用
    • カテゴリデータ → カテゴリ変数 と組み合わせ
    • 大規模・高次元 → 多変量分布 (共分散) など計算効率重視の派生を選択
  3. Step 3: 結果の解釈・共有は?
    • 専門家向け → 数値指標・統計検定で精緻に評価
    • 非専門家向け → 可視化・自然言語での要約を重視

このフローに沿って判断することで、 「確率分布のカタログ」を中核とした適切な手法選択ができる。

🔭 解説深化 — 分布の「家系図」と分散/平均テスト

このページは 9 つの分布を横断的にカタログ化しています。ここでは姉妹ページ(確率分布正規分布)とは重複しない角度として、「分布どうしの乗り換え(近似)はいつ成立し、いつ破綻するか」を、SSDSE-B-2026 の実測値で検証します。合言葉は 分散/平均(index of dispersion)です。

🧭 直感

同じ「数える現象」でも、見るスケールによって最適なレンズ(分布)が変わります。分布は独立に暗記するものではなく、1 本の家系図で繋がっています。

つまり 二項 → ポアソン → 正規 は「まれ・小規模」から「頻繁・大規模」へと連続的に繋がる一本道です。どのレンズを使うべきかは、数える対象の 規模で決まります。

⚠️ 落とし穴(重要)

「出生数・死亡数のようなカウントデータだからポアソン分布だろう」と反射的に決めるのが最頻出の罠です。ポアソン分布は理論上 平均 = 分散(分散/平均 = 1)という強い性質を持ちます。これを 47 都道府県(2023 年)の実測値でテストすると、次のように桁違いに過分散していました。

系列(2023, n=47) 平均 分散 分散/平均 最小〜最大(県)
出生数(A4101) 15,473.8 2.943×10⁸ 約 19,020 3,263 〜 86,348
死亡数(A4200) 33,512.4 8.458×10⁸ 約 25,238 8,290 〜 137,241
婚姻件数(A9101) 10,100.9 1.706×10⁸ 約 16,889 1,810 〜 71,774
離婚件数(A9201) 3,910.9 1.755×10⁷ 約 4,487 781 〜 20,016

※ すべて data/raw/SSDSE-B-2026.csvskiprows=[1]df[df['SSDSE-B-2026']==2023])の実測値。分散は不偏分散(ddof=1)。

ポアソンなら 1 のはずの分散/平均が 4,000〜25,000。これは「都道府県ごとに人口規模が全く違う」ためです。実際、出生数は鳥取県 3,263 に対し東京都 86,348、死亡数は鳥取県 8,290 に対し東京都 137,241 と、規模の異なる集団を一つの分布に混ぜている。異質なレート λ を持つポアソンを重ね合わせると、分散が平均をはるかに超える 過分散(overdispersion)になります。「カウント=ポアソン」は誤りです。

📝 「1 県だけの時系列なら混ざっていないからポアソンでは?」という第二の罠。鳥取県の 2012→2023 を時系列(12 年)で見ても、出生数は 4,771→3,263(分散/平均 ≈ 55.0、少子化トレンドで減少)、死亡数は 7,074→8,290(分散/平均 ≈ 19.5、高齢化トレンドで増加)。混合を排除してもトレンド(非定常性)があれば分散/平均は 1 に戻りません。ポアソン仮定は「レート一定」が前提です。

分散/平均 の相対的な大きさをバーで示すと(対数目盛イメージ、Poisson の基準 = 1 は左端):

出生数
≈19,020
死亡数
≈25,238
婚姻 
≈16,889
離婚 
≈4,487
鳥取・死亡(時系列)
≈19.5
Poisson の理論値
=1

🚀 発展

過分散に気づいたら、乗り換え先は主に 3 つです。

  1. 負の二項分布(Negative Binomial) — ポアソンのレート λ 自体をガンマ分布で揺らした混合分布。分散 = 平均 + α·平均² と、平均を超える分散を自然に許容する。過分散カウントの第一選択。
  2. レート化+オフセット(GLM) — 「件数」ではなく「人口あたりの発生率」をモデル化する。ポアソン回帰で log(人口) をオフセットに入れると、規模差による見かけの過分散を吸収できる。
  3. 正規近似に乗り換える — λ が十分大きい系列(今回はすべて数千〜十万規模)では、個々の県のカウントは既に正規で近似できる。正規分布ページの 68-95-99.7 ルールがそのまま使える。ただし県間の分布は右に裾を引く(対数正規寄り)ので、対数変換してから正規性を評価するのが定石です。

家系図として一行で覚えると:二項 →(n大・p小)→ ポアソン →(λ大, CLT)→ 正規、そしてポアソン →(λをガンマで揺らす)→ 負の二項。「どの近似が使えるか」は常に 分散/平均 を計算してから判断します。

🔗 関連ページ