第5回 統計的推定
はじめに
本シリーズ「Pythonで学ぶデータ分析実践」の第5回では、統計的推定について解説します。
実際のデータ分析では、母集団全体のデータを取得することが困難なケースがほとんどです。例えば「日本人全員の平均身長」を知りたい場合に、全員を測定することは現実的ではありません。そこで、一部のデータ(標本)から母集団の特徴を推定する統計的推定が重要になります。
本記事では、点推定と区間推定の考え方、中心極限定理、正規分布やt分布を用いた区間推定の方法を、Pythonのコードとともに実践的に解説します。
シリーズ全体の構成(全12回)
| 回 | テーマ |
|---|---|
| 第1回 | データ分析とは |
| 第2回 | データの前処理 |
| 第3回 | データの把握 |
| 第4回 | 相関分析 |
| 第5回 | 統計的推定(本記事) |
| 第6回 | 統計的検定 |
| 第7回 | 分散分析 |
| 第8回 | 回帰分析 |
| 第9回 | 時系列データ分析 |
| 第10回 | クラス分類 |
| 第11回 | クラスタリング |
| 第12回 | 次元削減 |
5-1. 母集団と標本
統計的推定とは、推定したい集団の一部のデータ(標本)から、集団全体(母集団)の特徴を推定する方法です。
基本用語の整理
| 用語 | 説明 | 例 |
|---|---|---|
| 母集団 | 推測したい集団全体 | 日本人全員、ある工場の全製品 |
| 母数(パラメータ) | 母集団の特徴を表す値 | 母平均μ、母分散σ² |
| 標本調査 | 集団の一部を対象とする調査 | 1000人へのアンケート |
| 標本(サンプル) | 標本調査の対象データ | 抽出された1000人分のデータ |
| 標本の大きさ(n) | 標本に含まれるデータの個数 | n = 1000 |
| 標本統計量 | 標本から計算される値 | 標本平均、標本分散 |
全数調査と標本調査
| 項目 | 全数調査 | 標本調査 |
|---|---|---|
| 対象 | 母集団全体 | 母集団の一部 |
| メリット | 正確な値が得られる | コスト・時間が少ない |
| デメリット | コスト・時間が膨大 | 推定に誤差が含まれる |
| 例 | 国勢調査 | 視聴率調査、出口調査 |
なぜ標本調査が必要か
- 母集団が大きすぎて全数調査が不可能(全国民の体重測定など)
- 調査が破壊的(製品の耐久テストなど)
- コスト・時間の制約がある
- リアルタイム性が求められる
標本抽出の方法
統計的推定が正しく機能するためには、標本が母集団を偏りなく代表している必要があります。
| 抽出方法 | 説明 |
|---|---|
| 単純無作為抽出 | 母集団から等確率でランダムに抽出 |
| 層化抽出 | 母集団をグループに分け、各グループから抽出 |
| クラスター抽出 | 母集団をまとまり(クラスター)に分け、選ばれたクラスターから全数調査 |
| 系統抽出 | 一定間隔で対象を選ぶ |
import numpy as np
import pandas as pd
# 母集団の生成(例: 全社員10000人の年収データ)
np.random.seed(42)
population = np.random.normal(loc=500, scale=100, size=10000) # 平均500万円、標準偏差100万円
print(f"母集団のサイズ: {len(population)}")
print(f"母平均 μ: {population.mean():.2f}万円")
print(f"母標準偏差 σ: {population.std():.2f}万円")
# 標本の抽出(単純無作為抽出)
sample_size = 100
sample = np.random.choice(population, size=sample_size, replace=False)
print(f"\n標本のサイズ: {len(sample)}")
print(f"標本平均: {sample.mean():.2f}万円")
print(f"標本標準偏差: {sample.std(ddof=1):.2f}万円")
5-2. 標本抽出
同じ母集団から標本を繰り返し抽出すると、標本ごとに標本統計量(平均値など)が異なる値をとります。この性質を理解することが、統計的推定の基礎となります。
標本分布
「標本統計量」は一般的に、標本ごとに異なる値を取ります。同じ母集団から何度も標本を抽出し、それぞれの標本平均を計算すると、その標本平均自体も一つの分布を形成します。これを標本分布と呼びます。
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
np.random.seed(42)
# 母集団(平均500、標準偏差100)
population = np.random.normal(loc=500, scale=100, size=10000)
# 標本平均を1000回繰り返し計算
n_trials = 1000
sample_size = 50
sample_means = []
for _ in range(n_trials):
sample = np.random.choice(population, size=sample_size, replace=False)
sample_means.append(sample.mean())
sample_means = np.array(sample_means)
# 可視化
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# 母集団の分布
axes[0].hist(population, bins=50, edgecolor='black', alpha=0.7, color='lightblue')
axes[0].axvline(population.mean(), color='red', linestyle='--', label=f'母平均: {population.mean():.1f}')
axes[0].set_title("母集団の分布", fontsize=13)
axes[0].set_xlabel("年収(万円)")
axes[0].set_ylabel("度数")
axes[0].legend()
# 標本平均の分布(標本分布)
axes[1].hist(sample_means, bins=30, edgecolor='black', alpha=0.7, color='lightcoral')
axes[1].axvline(sample_means.mean(), color='red', linestyle='--',
label=f'標本平均の平均: {sample_means.mean():.1f}')
axes[1].set_title(f"標本平均の分布(n={sample_size}, 試行{n_trials}回)", fontsize=13)
axes[1].set_xlabel("標本平均(万円)")
axes[1].set_ylabel("度数")
axes[1].legend()
plt.tight_layout()
plt.show()
print(f"標本平均の平均: {sample_means.mean():.2f}")
print(f"標本平均の標準偏差(標準誤差): {sample_means.std():.2f}")
print(f"理論的な標準誤差: {population.std() / np.sqrt(sample_size):.2f}")
不偏性
標本平均には不偏性という重要な性質があります。これは、標本平均の期待値(多数回抽出した場合の平均値)が母平均と一致する性質です。
$$E[\bar{X}] = \mu$$
つまり、標本平均を何度も計算して平均すれば、母平均に近づきます。この性質により、標本平均は母平均の良い推定量(不偏推定量)となります。
5-3. 点推定
点推定とは、標本データから母数を1つの値で推定する方法です。推定結果が1つの値なので「ピンポイント」で当たる確率は低いですが、最も尤もらしい値を求めることができます。
母平均μの点推定
母平均μの点推定値は標本平均 $\bar{x}$ で推定します。標本サイズnが大きくなるほど、標本平均は母平均に近づきます。
$$\hat{\mu} = \bar{x} = \frac{1}{n}\sum_{i=1}^{n}x_i$$
母分散σ²の点推定
標本分散はそのまま使うと真の母分散より小さくなる傾向があります。このため、母分散の推定には不偏分散 $s^2$ を使います。
$$s^2 = \frac{1}{n-1}\sum_{i=1}^{n}(x_i - \bar{x})^2$$
- n-1 で割る理由:標本平均を使って偏差を計算するため、自由度が1つ失われる
- n-1 を自由度と呼ぶ
不偏標準偏差
不偏分散の平方根を不偏標準偏差と呼びます。
$$s = \sqrt{\frac{1}{n-1}\sum_{i=1}^{n}(x_i - \bar{x})^2}$$
Pythonでの点推定
import numpy as np
# 母集団(真の値)
np.random.seed(42)
population = np.random.normal(loc=170, scale=8, size=100000) # 身長データ
print(f"=== 母集団の真の値 ===")
print(f"母平均 μ: {population.mean():.4f} cm")
print(f"母分散 σ²: {population.var():.4f}")
print(f"母標準偏差 σ: {population.std():.4f} cm")
# 標本を抽出して点推定
sample = np.random.choice(population, size=30, replace=False)
print(f"\n=== 標本からの点推定(n=30) ===")
print(f"標本平均 x̄(母平均の推定値): {sample.mean():.4f} cm")
print(f"不偏分散 s²(母分散の推定値): {sample.var(ddof=1):.4f}")
print(f"不偏標準偏差 s(母標準偏差の推定値): {sample.std(ddof=1):.4f} cm")
# サンプルサイズを変えて精度を比較
print(f"\n=== サンプルサイズによる推定精度の変化 ===")
for n in [10, 30, 100, 500, 1000]:
sample = np.random.choice(population, size=n, replace=False)
print(f"n={n:5d}: 標本平均={sample.mean():.3f}, "
f"誤差={abs(sample.mean() - population.mean()):.3f} cm")
点推定の限界
点推定は1つの値を返すだけなので、以下の疑問に答えることができません。
- その推定値はどれくらい正確なのか?
- 真の値はどの程度の範囲にあるのか?
この限界を補うのが、次に解説する区間推定です。
5-4. 区間推定
区間推定は、母数が含まれると考えられる範囲(区間)を確率付きで推定する方法です。点推定と異なり「○○%の確率で母平均はこの範囲にある」と表現するため、推定の信頼性が明確になります。
区間推定の基本概念
| 用語 | 説明 |
|---|---|
| 信頼度(信頼水準) | 推定区間が母数を含む確率。一般的に95%を使用 |
| 信頼区間 | 母数が含まれると推定される範囲 |
| 信頼限界(上限・下限) | 信頼区間の両端の値 |
例:「95%の信頼度で母平均は58点〜62点の範囲にある」
- 信頼度:95%
- 信頼区間:58点〜62点
- 下側信頼限界:58点
- 上側信頼限界:62点
中心極限定理
区間推定の理論的基盤となるのが中心極限定理です。
中心極限定理: 母集団の分布に関わらず、標本サイズnが十分大きければ、標本平均の分布は正規分布 $N(\mu, \frac{\sigma^2}{n})$ に近似できる。
つまり、母集団がどのような分布であっても(歪んでいても)、標本平均は正規分布に従うということです。
中心極限定理の可視化
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
np.random.seed(42)
# さまざまな母集団分布で中心極限定理を確認
fig, axes = plt.subplots(3, 3, figsize=(15, 12))
distributions = {
"一様分布": np.random.uniform(0, 100, 10000),
"指数分布": np.random.exponential(50, 10000),
"二項分布": np.random.binomial(10, 0.3, 10000),
}
sample_sizes = [5, 30, 100]
for row, (dist_name, population) in enumerate(distributions.items()):
for col, n in enumerate(sample_sizes):
means = [np.random.choice(population, n).mean() for _ in range(1000)]
axes[row, col].hist(means, bins=30, edgecolor='black', alpha=0.7,
density=True, color='steelblue')
axes[row, col].set_title(f"{dist_name}\nn={n}", fontsize=10)
if col == 0:
axes[row, col].set_ylabel("確率密度")
fig.suptitle("中心極限定理: 標本サイズが大きくなると標本平均の分布は正規分布に近づく",
fontsize=13)
plt.tight_layout()
plt.show()
標準誤差(Standard Error: SE)
標本平均の標本分布の標準偏差を標準誤差(SE)と呼びます。
$$SE = \frac{\sigma}{\sqrt{n}}$$
母分散が未知の場合(通常こちら)は、不偏標準偏差sで代用します。
$$SE = \frac{s}{\sqrt{n}}$$
標準誤差の性質:
- SEが小さい → 標本平均のばらつきが小さい → 推定精度が高い
- nが大きい → SEが小さくなる → 推定精度が向上
- SE を半分にするには、サンプルサイズを4倍にする必要がある
import numpy as np
# 標準誤差の計算
sample = np.array([165, 170, 172, 168, 175, 180, 162, 171, 169, 173])
n = len(sample)
se = sample.std(ddof=1) / np.sqrt(n)
print(f"標本平均: {sample.mean():.2f}")
print(f"不偏標準偏差: {sample.std(ddof=1):.2f}")
print(f"標準誤差 SE: {se:.2f}")
print(f"サンプルサイズ n: {n}")
5-5. 信頼区間
母平均の区間推定
母平均μの信頼区間は、使用する分布(正規分布 or t分布)によって計算方法が異なります。
正規分布を使う場合(母分散既知、またはn≧30)
母分散σ²が既知の場合、または標本サイズが30以上の場合、正規分布を用いて区間推定を行います。
95%信頼区間:
$$\bar{x} - 1.96 \times \frac{\sigma}{\sqrt{n}} \leq \mu \leq \bar{x} + 1.96 \times \frac{\sigma}{\sqrt{n}}$$
- 1.96 は標準正規分布の97.5パーセント点(両側5%点)
import numpy as np
from scipy import stats
# 例: ある工場の製品重量(母標準偏差σ=5gが既知)
sample = np.array([198, 202, 195, 201, 199, 203, 197, 200, 204, 196,
201, 198, 203, 199, 200, 202, 197, 201, 199, 200,
198, 203, 201, 199, 200, 202, 197, 201, 199, 200])
sigma = 5 # 母標準偏差(既知)
n = len(sample)
x_bar = sample.mean()
# 95%信頼区間(正規分布)
confidence = 0.95
z = stats.norm.ppf((1 + confidence) / 2) # 1.96
se = sigma / np.sqrt(n)
lower = x_bar - z * se
upper = x_bar + z * se
print(f"=== 正規分布による母平均の区間推定 ===")
print(f"標本平均: {x_bar:.2f} g")
print(f"標準誤差 SE: {se:.4f}")
print(f"z値 (95%): {z:.4f}")
print(f"95%信頼区間: [{lower:.2f}, {upper:.2f}] g")
# scipy.stats.norm.interval を使う方法
ci = stats.norm.interval(confidence, loc=x_bar, scale=se)
print(f"scipy利用: [{ci[0]:.2f}, {ci[1]:.2f}] g")
t分布を使う場合(母分散未知、かつn<30)
母分散が未知で標本サイズが小さい(n<30)場合は、正規分布の代わりにt分布を使用します。
t分布の特徴:
- 正規分布に似ているが、中央のピークがより低く、裾が広い
- 小さいサンプルサイズでの極端なデータ点をより適切に表現できる
- 自由度(n-1)が大きくなると正規分布に近づく
- 自由度が30程度で、ほぼ正規分布と一致する
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
import japanize_matplotlib
# t分布と正規分布の比較
x = np.linspace(-4, 4, 200)
plt.figure(figsize=(10, 6))
plt.plot(x, stats.norm.pdf(x), 'k-', linewidth=2, label='正規分布 N(0,1)')
for df in [1, 3, 10, 30]:
plt.plot(x, stats.t.pdf(x, df), '--', linewidth=1.5, label=f't分布 (自由度={df})')
plt.xlabel("x", fontsize=12)
plt.ylabel("確率密度", fontsize=12)
plt.title("t分布と正規分布の比較", fontsize=14)
plt.legend(fontsize=10)
plt.grid(alpha=0.3)
plt.show()
t分布による95%信頼区間:
$$\bar{x} - t_{\alpha/2}(n-1) \times \frac{s}{\sqrt{n}} \leq \mu \leq \bar{x} + t_{\alpha/2}(n-1) \times \frac{s}{\sqrt{n}}$$
import numpy as np
from scipy import stats
# 例: 新薬の効果測定(15人の被験者)
sample = np.array([5.2, 4.8, 6.1, 5.5, 4.9, 5.7, 6.3, 5.0,
5.4, 4.6, 5.8, 6.0, 5.3, 4.7, 5.6])
n = len(sample)
x_bar = sample.mean()
s = sample.std(ddof=1) # 不偏標準偏差
se = s / np.sqrt(n)
# 95%信頼区間(t分布)
confidence = 0.95
df = n - 1 # 自由度
t_value = stats.t.ppf((1 + confidence) / 2, df)
lower = x_bar - t_value * se
upper = x_bar + t_value * se
print(f"=== t分布による母平均の区間推定 ===")
print(f"標本サイズ n: {n}")
print(f"標本平均: {x_bar:.4f}")
print(f"不偏標準偏差 s: {s:.4f}")
print(f"標準誤差 SE: {se:.4f}")
print(f"自由度: {df}")
print(f"t値 (95%, df={df}): {t_value:.4f}")
print(f"95%信頼区間: [{lower:.4f}, {upper:.4f}]")
# scipy.stats.t.interval を使う方法
ci = stats.t.interval(confidence, df, loc=x_bar, scale=se)
print(f"scipy利用: [{ci[0]:.4f}, {ci[1]:.4f}]")
正規分布とt分布の使い分け
| 条件 | 使用する分布 | 理由 |
|---|---|---|
| 母分散σ²が既知 | 正規分布 | 標本平均が正規分布に従う |
| n ≧ 30、母分散未知 | 正規分布(近似) | 中心極限定理により近似可能 |
| n < 30、母分散未知 | t分布 | 小標本では裾の広いt分布が適切 |
信頼度を変えた場合の比較
import numpy as np
from scipy import stats
sample = np.array([5.2, 4.8, 6.1, 5.5, 4.9, 5.7, 6.3, 5.0,
5.4, 4.6, 5.8, 6.0, 5.3, 4.7, 5.6])
n = len(sample)
x_bar = sample.mean()
se = sample.std(ddof=1) / np.sqrt(n)
df = n - 1
print("=== 信頼度別の信頼区間 ===")
for confidence in [0.90, 0.95, 0.99]:
ci = stats.t.interval(confidence, df, loc=x_bar, scale=se)
width = ci[1] - ci[0]
print(f"信頼度{confidence*100:.0f}%: [{ci[0]:.4f}, {ci[1]:.4f}] "
f"(幅: {width:.4f})")
# → 信頼度を上げると区間は広くなる(精度とのトレードオフ)
信頼区間の可視化
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
import japanize_matplotlib
np.random.seed(42)
# 母集団
population = np.random.normal(loc=50, scale=10, size=100000)
true_mean = population.mean()
# 20回の標本抽出で信頼区間を計算
n_experiments = 20
sample_size = 30
plt.figure(figsize=(10, 8))
contains_true = 0
for i in range(n_experiments):
sample = np.random.choice(population, size=sample_size, replace=False)
x_bar = sample.mean()
se = sample.std(ddof=1) / np.sqrt(sample_size)
ci = stats.t.interval(0.95, sample_size-1, loc=x_bar, scale=se)
# 真の母平均を含むかどうかで色を変える
if ci[0] <= true_mean <= ci[1]:
color = 'steelblue'
contains_true += 1
else:
color = 'red'
plt.plot([ci[0], ci[1]], [i, i], color=color, linewidth=2)
plt.plot(x_bar, i, 'o', color=color, markersize=6)
plt.axvline(true_mean, color='green', linestyle='--', linewidth=2,
label=f'真の母平均: {true_mean:.2f}')
plt.xlabel("値", fontsize=12)
plt.ylabel("実験番号", fontsize=12)
plt.title(f"95%信頼区間の繰り返し実験({n_experiments}回中{contains_true}回が母平均を含む)",
fontsize=13)
plt.legend(fontsize=11)
plt.grid(alpha=0.3, axis='x')
plt.show()
母比率の区間推定
母比率の区間推定は、母集団における特定の事象が起こる割合(比率)を推定する方法です。
二項分布
二項分布は、結果が2つだけの事象(成功/失敗)の確率分布です。
$$f(k) = \binom{n}{k} p^k (1-p)^{n-k}$$
- n: 試行回数
- p: 1回の試行で事象が起こる確率
- k: 事象が起こった回数
二項分布 $Bin(n, p)$ の特性:
- 平均: $np$
- 分散: $np(1-p)$
二項分布の可視化
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
import japanize_matplotlib
# 二項分布の可視化
n_trials = 100
p = 0.3
x = np.arange(0, n_trials + 1)
pmf = stats.binom.pmf(x, n_trials, p)
plt.figure(figsize=(10, 6))
plt.bar(x, pmf, color='steelblue', alpha=0.7, edgecolor='black', linewidth=0.5)
plt.axvline(n_trials * p, color='red', linestyle='--', linewidth=2,
label=f'期待値 np = {n_trials * p}')
plt.xlabel("事象が起こった回数 k", fontsize=12)
plt.ylabel("確率 P(X=k)", fontsize=12)
plt.title(f"二項分布 Bin(n={n_trials}, p={p})", fontsize=14)
plt.legend(fontsize=11)
plt.xlim(10, 50)
plt.grid(alpha=0.3)
plt.show()
print(f"平均: np = {n_trials * p}")
print(f"分散: np(1-p) = {n_trials * p * (1-p)}")
print(f"標準偏差: √np(1-p) = {np.sqrt(n_trials * p * (1-p)):.2f}")
母比率の95%信頼区間
nが十分に大きいとき、標本比率の分布は正規分布に近似できます(中心極限定理)。
$$\hat{p} - 1.96\sqrt{\frac{\hat{p}(1-\hat{p})}{n}} \leq p \leq \hat{p} + 1.96\sqrt{\frac{\hat{p}(1-\hat{p})}{n}}$$
- $\hat{p}$: 標本比率
- n: 標本サイズ
import numpy as np
from scipy import stats
# 実践例: 選挙の出口調査
# 100人に調査した結果、65人がA候補を支持
n = 100 # 標本サイズ
k = 65 # 支持者数
p_hat = k / n # 標本比率
# 正規近似による95%信頼区間
confidence = 0.95
z = stats.norm.ppf((1 + confidence) / 2)
se = np.sqrt(p_hat * (1 - p_hat) / n)
lower = p_hat - z * se
upper = p_hat + z * se
print(f"=== 母比率の区間推定(正規近似) ===")
print(f"標本サイズ n: {n}")
print(f"支持者数: {k}")
print(f"標本比率 p̂: {p_hat:.4f} ({p_hat*100:.1f}%)")
print(f"標準誤差 SE: {se:.4f}")
print(f"95%信頼区間: [{lower:.4f}, {upper:.4f}]")
print(f" = [{lower*100:.1f}%, {upper*100:.1f}%]")
print()
# 判定: 50%を超えるか
if lower > 0.5:
print("→ 95%信頼区間の下限が50%を超えているため、")
print(" 当選の可能性が高いと判断できます。")
else:
print("→ 95%信頼区間の下限が50%以下のため、")
print(" 当選するかどうかは断言できません。")
scipy.stats.binom を使った方法
from scipy import stats
# 二項分布を直接使った信頼区間(Clopper-Pearson法: 正確な方法)
n = 100
k = 65
confidence = 0.95
# Clopper-Pearson法(正確な二項信頼区間)
alpha = 1 - confidence
lower_cp = stats.beta.ppf(alpha / 2, k, n - k + 1)
upper_cp = stats.beta.ppf(1 - alpha / 2, k + 1, n - k)
print(f"=== Clopper-Pearson法による正確な信頼区間 ===")
print(f"95%信頼区間: [{lower_cp:.4f}, {upper_cp:.4f}]")
print(f" = [{lower_cp*100:.1f}%, {upper_cp*100:.1f}%]")
補足:実践的な統計的推定のポイント
サンプルサイズの決め方
推定精度(信頼区間の幅)を事前に決めたい場合、必要なサンプルサイズを逆算できます。
母平均の区間推定に必要なサンプルサイズ
95%信頼区間の幅を $E$ 以下にしたい場合:
$$n \geq \left(\frac{z \cdot \sigma}{E}\right)^2$$
from scipy import stats
import numpy as np
# 例: 95%信頼区間の幅を±2以内にしたい
# 過去のデータから標準偏差は約10と推定
sigma_est = 10
E = 2 # 許容誤差
confidence = 0.95
z = stats.norm.ppf((1 + confidence) / 2)
n_required = (z * sigma_est / E) ** 2
print(f"=== 必要サンプルサイズの計算 ===")
print(f"推定標準偏差: {sigma_est}")
print(f"許容誤差: ±{E}")
print(f"信頼度: {confidence*100}%")
print(f"必要サンプルサイズ: {int(np.ceil(n_required))}以上")
母比率の区間推定に必要なサンプルサイズ
# 例: 内閣支持率を±3%の精度で推定したい
E = 0.03 # 許容誤差(3%)
p_est = 0.5 # 最も保守的な仮定(分散最大)
z = stats.norm.ppf(0.975)
n_required = (z ** 2) * p_est * (1 - p_est) / (E ** 2)
print(f"必要サンプルサイズ: {int(np.ceil(n_required))}以上")
# → 約1068人必要
信頼区間に関するよくある誤解
| 誤った解釈 | 正しい解釈 |
|---|---|
| 「母平均が95%の確率でこの区間に入る」 | 「同じ方法で100回推定したら、約95回は母平均を含む区間が得られる」 |
| 「次の標本平均が95%の確率でこの区間に入る」 | 信頼区間は母数(固定値)に対する推定であり、将来の標本に対する予測ではない |
| 「信頼度を上げれば推定精度が上がる」 | 信頼度を上げると区間が広がる(精度とのトレードオフ) |
実践例:A/Bテストでの区間推定
import numpy as np
from scipy import stats
# Webサイトのコンバージョン率のA/Bテスト
# パターンA: 1000人中120人がコンバージョン
# パターンB: 1000人中150人がコンバージョン
n_a, k_a = 1000, 120
n_b, k_b = 1000, 150
p_a = k_a / n_a
p_b = k_b / n_b
# 各パターンの95%信頼区間
z = stats.norm.ppf(0.975)
se_a = np.sqrt(p_a * (1 - p_a) / n_a)
ci_a = (p_a - z * se_a, p_a + z * se_a)
se_b = np.sqrt(p_b * (1 - p_b) / n_b)
ci_b = (p_b - z * se_b, p_b + z * se_b)
# 差の信頼区間
diff = p_b - p_a
se_diff = np.sqrt(se_a**2 + se_b**2)
ci_diff = (diff - z * se_diff, diff + z * se_diff)
print(f"=== A/Bテストの結果 ===")
print(f"パターンA: CVR={p_a*100:.1f}%, 95%CI=[{ci_a[0]*100:.1f}%, {ci_a[1]*100:.1f}%]")
print(f"パターンB: CVR={p_b*100:.1f}%, 95%CI=[{ci_b[0]*100:.1f}%, {ci_b[1]*100:.1f}%]")
print(f"差 (B-A): {diff*100:.1f}%, 95%CI=[{ci_diff[0]*100:.1f}%, {ci_diff[1]*100:.1f}%]")
print()
if ci_diff[0] > 0:
print("→ 差の信頼区間が0を含まないため、BはAより有意に高いと判断できます。")
else:
print("→ 差の信頼区間が0を含むため、有意な差があるとは断言できません。")
区間推定のまとめフロー
1. 推定したい母数を特定する(母平均 or 母比率)
2. 標本を無作為に抽出する
3. 信頼度を決める(通常95%)
4. 使用する分布を選択する
- 母分散既知 or n≧30 → 正規分布
- 母分散未知 かつ n<30 → t分布
5. 信頼区間を計算する
6. 結果を解釈する
まとめ
本記事では、統計的推定として以下の内容を解説しました。
| 項目 | ポイント |
|---|---|
| 母集団と標本 | 母集団全体を調べるのは困難なため、標本から推定する |
| 標本抽出 | 標本分布と不偏性、中心極限定理が推定の基盤 |
| 点推定 | 標本平均→母平均、不偏分散→母分散を1点で推定 |
| 区間推定 | 信頼度付きの範囲で推定。実用的な手法 |
| 信頼区間 | 正規分布(n≧30)またはt分布(n<30)で計算 |
| 母比率の推定 | 二項分布の正規近似を利用 |
統計的推定のチェックリスト
- 推定の目的(何を知りたいか)を明確にしたか
- 標本が母集団を偏りなく代表しているか確認したか
- 適切なサンプルサイズを確保しているか
- 正規分布とt分布のどちらを使うべきか判断したか
- 信頼度を設定したか(通常95%)
- 信頼区間の解釈を正しく行っているか
- 必要に応じてサンプルサイズの計算を行ったか
シリーズ記事一覧
- 【第1回】Pythonで学ぶデータ分析実践 〜データ分析とは〜
- 【第2回】データの前処理(欠損値・外れ値・ダミー変数・データスケーリングなど)
- 【第3回】データの把握(基本統計量・ヒストグラム・箱ひげ図・散布図など)
- 【第4回】相関分析(共分散・相関係数・相関比・連関係数など)
- 【第5回】統計的推定(母集団と標本・点推定・区間推定・信頼区間)
- 【第6回】統計的検定(仮説検定・p値・t検定・カイ二乗検定など)
- 【第7回】分散分析(一元分散分析・二元分散分析・多重比較)
- 【第8回】回帰分析(単回帰・重回帰・一般化線形モデル・モデル評価)
- 【第9回】時系列データ分析(トレンド・季節性・ARIMA・SARIMAなど)
- 【第10回】クラス分類(決定木・ランダムフォレスト・ロジスティック回帰など)
- 【第11回】クラスタリング(k-means・階層クラスタリング・エルボー法など)
- 【第12回】次元削減(主成分分析・寄与率・可視化)
- 【発展編】分析精度の向上(特徴量エンジニアリング・ハイパーパラメータ調整・アンサンブル学習など)
- 【発展編】ニューラルネットワーク入門(パーセプトロン・誤差逆伝播法・TensorFlow・Kerasなど)
次回の第6回では、統計的推定の知識を土台として、仮説検定の考え方を解説します。p値、有意水準、t検定、カイ二乗検定など、データに基づいて「差がある」と判断するための手法を学びます。