仮説検定
田中VPoE「NetShop社のマーケティング部門から、面白い報告が来ている。『新しいレコメンドエンジンを導入した地域の売上が上がった気がする』と。」
あなた「『気がする』ですか。実際にデータで確認すればいいですよね。」
田中VPoE「そう、でも単に平均を比較するだけでは不十分だ。偶然の差なのか、本当に意味のある差なのかを統計的に判断する必要がある。それが仮説検定だ。」
仮説検定とは
仮説検定は、「観察された差が偶然によるものか、統計的に有意な差なのか」を判断する手法です。
基本的な手順
- 帰無仮説(H0)を立てる:「差がない」「効果がない」
- 対立仮説(H1)を立てる:「差がある」「効果がある」
- 検定統計量を計算する
- p値を求める
- 有意水準と比較して判断する
例:レコメンドエンジンの効果
- H0(帰無仮説):新レコメンドエンジンの導入前後で平均注文金額に差はない
- H1(対立仮説):新レコメンドエンジンの導入後、平均注文金額が増加した
p値の理解
p値は「帰無仮説が正しい場合に、今回の結果以上に極端な結果が得られる確率」です。
| p値 | 解釈 | 判断 |
|---|---|---|
| p < 0.01 | 非常に強い証拠 | H0を棄却(有意差あり) |
| p < 0.05 | 十分な証拠 | H0を棄却(有意差あり) |
| 0.05 <= p < 0.10 | 弱い証拠 | 判断保留(傾向あり) |
| p >= 0.10 | 証拠不十分 | H0を棄却できない |
注意:p値は「差がない確率」ではありません。
t検定
2つのグループの平均に有意な差があるかを検定します。
独立2標本t検定
from scipy import stats
# グループA: レコメンドエンジン導入地域
group_a = df[df['region'] == '導入済み']['amount']
# グループB: 未導入地域
group_b = df[df['region'] == '未導入']['amount']
# 独立2標本t検定
t_stat, p_value = stats.ttest_ind(group_a, group_b)
print(f"t統計量: {t_stat:.3f}")
print(f"p値: {p_value:.4f}")
if p_value < 0.05:
print("→ 有意水準5%で有意差あり")
else:
print("→ 有意水準5%で有意差なし")
対応のあるt検定
同じ対象の前後を比較する場合:
# 同じ顧客の施策前後を比較
before = df_paired['amount_before']
after = df_paired['amount_after']
t_stat, p_value = stats.ttest_rel(before, after)
print(f"p値: {p_value:.4f}")
t検定の前提条件
| 前提条件 | 確認方法 | 満たさない場合 |
|---|---|---|
| 正規性 | Shapiro-Wilk検定 | Welchのt検定 or Mann-Whitney U検定 |
| 等分散性 | Levene検定 | Welchのt検定(equal_var=False) |
| 独立性 | 実験設計で確保 | 対応のあるt検定を使用 |
# 等分散性を仮定しないWelchのt検定(推奨)
t_stat, p_value = stats.ttest_ind(group_a, group_b, equal_var=False)
カイ二乗検定
カテゴリカル変数間の関連性を検定します。
# クロス集計表の作成
contingency = pd.crosstab(df['gender'], df['purchased'])
print(contingency)
# カイ二乗検定
chi2, p_value, dof, expected = stats.chi2_contingency(contingency)
print(f"カイ二乗統計量: {chi2:.3f}")
print(f"p値: {p_value:.4f}")
print(f"自由度: {dof}")
使用例:「性別と購入の有無に関連があるか?」
効果量
p値だけでは「差の大きさ」はわかりません。効果量を一緒に報告しましょう。
Cohen’s d(t検定の効果量)
def cohens_d(group1, group2):
n1, n2 = len(group1), len(group2)
var1, var2 = group1.var(), group2.var()
pooled_std = np.sqrt(((n1-1)*var1 + (n2-1)*var2) / (n1+n2-2))
return (group1.mean() - group2.mean()) / pooled_std
d = cohens_d(group_a, group_b)
print(f"Cohen's d: {d:.3f}")
| Cohen’s d | 効果の大きさ |
|---|---|
| 0.2 | 小さい |
| 0.5 | 中程度 |
| 0.8 | 大きい |
多重比較問題
複数の検定を同時に行うと、偶然に有意になるリスクが増大します。
# Bonferroni補正
alpha = 0.05
n_tests = 10
corrected_alpha = alpha / n_tests # 0.005
# Holm法(より検出力が高い)
from statsmodels.stats.multitest import multipletests
p_values = [0.001, 0.013, 0.028, 0.042, 0.087, 0.12, 0.35, 0.56, 0.78, 0.92]
reject, corrected_p, _, _ = multipletests(p_values, method='holm')
print(pd.DataFrame({
'original_p': p_values,
'corrected_p': corrected_p,
'reject_H0': reject
}))
| 補正方法 | 特徴 | 適用場面 |
|---|---|---|
| Bonferroni | 最も保守的 | 少数の比較 |
| Holm | やや保守的 | 一般的な多重比較 |
| FDR (Benjamini-Hochberg) | 検出力重視 | 探索的分析 |
まとめ
| 項目 | ポイント |
|---|---|
| 仮説検定 | 帰無仮説を立て、p値で判断する |
| p値 | 0.05未満で有意(慣例)だが、効果量も報告する |
| t検定 | 2群の平均差の検定。Welchのt検定が推奨 |
| カイ二乗検定 | カテゴリカル変数間の関連性を検定 |
| 多重比較 | 複数検定時はBonferroniやHolm法で補正する |
チェックリスト
- 帰無仮説と対立仮説を設定できる
- p値の意味を正しく説明できる
- 独立2標本t検定を実行し、結果を解釈できる
- 多重比較問題の対策を理解している
次のステップへ
仮説検定を学びました。次は、変数間の関係性を測る相関分析を学びましょう。
推定読了時間:30分