仮説検定(hypothesis testing)を確実に理解するための関連キーワードを難易度別に整理しました。
「仮説検定」を理解するうえで必要なキーワードを 10 件以上提示します。 各チップから対応セクションへ移動できます。
30 秒結論 文脈 直感 数式 記号読み解き 実値計算 Python 実装 落とし穴 関連手法 関連用語 グループ教材 概念マップ
🍰 まずはやさしく
データで正解を判断する仕組みです。
主張が正しいかを決めるために使います。
部活の練習法で効果があるか調べます。
判定に使う重要な言葉を学びます。
「標本データから母集団についての主張を判断する」枠組み。 Fisher(1925)と Neyman-Pearson(1933)が体系化。 統計推論の中核ですが、 21世紀に入って多くの誤解と再現性危機が指摘されています。 本ページでは古典的体系を押さえつつ、 現代的な批判と改善も含めて解説します。
仮説検定は「背理法に似た論理」で進めます。 まず「差はない」「効果はない」という消極的な仮説 H₀を立て、 データがそれを否定するほど極端かを問います。
例:
💡 重要:「H₀ を棄却できなかった」≠「H₀ が真である」。 「証拠不十分」というだけ。 「効果がない」を主張するには別の枠組み(同等性検定など)が必要。
「H₀ が真と仮定したとき、 観測されたデータ(の検定統計量)と同じかそれ以上に極端な結果が偶然出る確率」。
$$ p = P(|T| \ge |t_\text{obs}| \mid H_0) $$
記号:$T$ は検定統計量(確率変数)、 $t_\text{obs}$ は観測された値、 $|\cdot|$ は両側検定の場合。
解釈:
| ❌ 誤った解釈 | ✅ 正しい解釈 |
|---|---|
| p = 0.03 → H₀ が真である確率は 3% | H₀ が真と仮定したときの確率(条件付き) |
| p < 0.05 → 効果が大きい | 「偶然じゃない」だけで効果量とは別 |
| p > 0.05 → 効果がない | 「証拠不十分」、 効果はあるかもしれない |
| p値が小さいほど信頼できる | サンプルサイズが大きいだけかもしれない |
2016 年の 米統計学会 (ASA) 声明は、 p値だけで結論を出さないことを強調。 効果量・信頼区間・複数アプローチを併用すべき。
「H₀ が真なのに棄却してしまう」誤り(第I種誤り、 false positive)を許容する確率。 事前に決めるべき。
| 分野 | 慣習的 α | 理由 |
|---|---|---|
| 心理学・社会学 | 0.05 | Fisher 由来の慣習 |
| 医療試験(FDA 承認) | 0.05(両側) | 承認基準 |
| 物理学(粒子発見) | 5σ ≈ 3×10⁻⁷ | 「発見」を主張する厳しさ |
| GWAS(遺伝子) | 5×10⁻⁸ | 100万 SNP の多重比較 |
| 経済学 | 0.05〜0.10 | サンプル取得困難 |
近年は「p < 0.05 という基準そのものを見直すべき」という議論も。 Benjamin et al.(2018)は「α = 0.005 を新標準に」と提案。
🍰 まずはやさしく
分析でよく出てくる用語の集まりです。
データの意味を正しく読み取るために使います。
スマホの利用時間と成績の関係を調べます。
基本の言葉から最新の考え方まで読みます。
論文・記事に 「p値」「有意水準」「帰無仮説」「対立仮説」「検出力」「効果量」「第I種誤り」「第II種誤り」「多重比較」 として登場する用語群。 推測統計の中核ですが、 21世紀になって多くの誤解と再現性危機が指摘されています。 古典的体系 + 現代的批判 + ベイズの代替を含めて学びます。
このセクションは「仮説検定」を扱う 用語ページ です。 統計データ分析コンペティション(2026)の再現教材における中核用語のひとつで、人口上位 10 県とそれ以外で出生数 (A4101) の平均に差があるかを検定 という観点で SSDSE-B-2026(47 都道府県 × 複数年 × 100 超列)に紐づけられます。
位置づけ:相関・線形回帰・仮説検定 といった基礎用語群と並列であり、応用としては 内生性・IV・DID・クラスタリング 等へ繋がります。
🍰 まずはやさしく
データを分析するための眼鏡のようなものです。
隠れた特徴を見つけ出すために使います。
地域によって買い物の傾向が違うか調べます。
この眼鏡を使ってデータを眺める方法を読みます。
仮説検定 を一言でいえば「群分けした都道府県の間で、 出生数 (A4101) のような指標の平均に差があるかをデータで判定する枠組み」。 47 都道府県という小さな母集団でも、 SSDSE-B-2026 の A4101 列(出生数)に注目すると、 大都市圏と地方の差・人口規模に伴う相対比較など、 様々なパターンが見えてきます。
比喩でいうと、 仮説検定 はデータ分析の「眼鏡」のようなもの。 同じデータでも眼鏡を変えれば、 平均(中心)・分散(ばらつき)・相関(連動)・因果(影響)と、 異なる情報が浮かび上がります。 SSDSE-B-2026 を題材に、 この眼鏡をかけてみるのが本ページの狙いです。
スライダーとボタンを動かすと、 帰無分布(H₀ が真のときの検定統計量の分布)の上に棄却域が塗られ、 観測統計量から p値がリアルタイムに再計算されます。 p < α なら H₀ を棄却、 そうでなければ保留(採択できず)を色で示します。 「過誤モード」に切り替えると、 対立分布との重なりで第一種の過誤 α・第二種の過誤 β・検出力 1−β を可視化します。
💡 グラフ上を左右にドラッグ/タップしても観測統計量を動かせます。 過誤モードは標準正規(シフトモデル)で α・β・検出力を厳密計算します(t の非心分布は扱いません)。
🍰 まずはやさしく
差がどれくらい大きいかを示す物差しです。
実質的な影響があるかを判断するために使います。
勉強法を変えて点数がどれだけ上がったか調べます。
数値の読み方と基準について読みます。
「p値が小さい」だけでは「効果が大きい」とは限らない。 効果の実質的な大きさを表すのが効果量。
| 場面 | 効果量 | 公式 | 小 / 中 / 大 |
|---|---|---|---|
| 2 群平均差 | Cohen's d | $(\mu_1 - \mu_2)/\sigma$ | 0.2 / 0.5 / 0.8 |
| 相関 | r | Pearson 相関係数 | 0.1 / 0.3 / 0.5 |
| 回帰 | R² | 決定係数 | 0.02 / 0.13 / 0.26 |
| ANOVA | η² (eta²) | 説明される分散 | 0.01 / 0.06 / 0.14 |
| χ² | Cramér's V | $\sqrt{\chi^2/(n(k-1))}$ | 0.1 / 0.3 / 0.5 |
| ロジスティック | Odds Ratio | オッズ比 | 1.5 / 2.5 / 4.0 |
Cohen の基準は慣習であって絶対ではない。 分野によって「中程度」の感覚は異なる。 医療では小さな効果量でも臨床的に重要、 心理学では中効果が標準など。
事前に「方向」が決まっているなら片側、 そうでなければ両側:
| タイプ | H₁ | 使い時 |
|---|---|---|
| 両側 | $\mu \ne \mu_0$ | 通常はこちら |
| 右片側 | $\mu > \mu_0$ | 「増加」だけ検出したい時 |
| 左片側 | $\mu < \mu_0$ | 「減少」だけ検出したい時 |
⚠️ データを見てから片側にするのは禁忌(p-hacking)。 必ず事前に決めること。
10 個の検定を $\alpha=0.05$ で行うと、 すべて H₀ が真でも偶然に有意になる確率は $1-0.95^{10} \approx 40\%$。 何も補正しないと「探索的に有意なペアを選んだ」状態になり、 再現性危機の温床になります。
| 補正法 | 概要 | 特徴 |
|---|---|---|
| Bonferroni | $\alpha / m$ で判定 | 最も保守的・厳しい |
| Holm | 段階的 Bonferroni | Bonf より検出力↑ |
| Benjamini-Hochberg (BH) | FDR(偽発見率)制御 | 現代の主流 |
| Tukey HSD | ANOVA 後の全ペア比較 | 事後検定用 |
1 2 3 4 5 6 7 8 9 | from statsmodels.stats.multitest import multipletests p_values = [0.001, 0.01, 0.03, 0.04, 0.10, 0.20] # Benjamini-Hochberg (FDR) rej, p_adj, _, _ = multipletests(p_values, alpha=0.05, method='fdr_bh') # Bonferroni rej, p_adj, _, _ = multipletests(p_values, alpha=0.05, method='bonferroni') |
仮説検定 の代表的な定義式は次のとおりです。
$$ \text{reject } H_0 \;\Leftrightarrow\; p\text{-value} < \alpha $$ここで使われる記号や演算の意味は次節で言葉に翻訳します。
数式の各記号を、日本語の意味に変換します。
仮説検定は、 帰無仮説 H0 と対立仮説 H1 を立てて、 観測データが H0 のもとで起こる確率(p 値)を計算し、 有意水準 α と比較して H0 を棄却するか判断する統計推測の基本枠組み。
仮説検定 (Hypothesis Testing) は、 統計・データ解析の文脈で頻繁に登場する概念です。 ここでは初学者向けの直感と、 上級者向けの形式定義を併記します。
「東京都の高齢化率は全国的な水準より低いか?」を 1 標本 t 検定の枠組みで考える。 H0: μ = 0.316(2023 年・47 都道府県の高齢化率 A1303/A1101 の単純平均、 実測値)、 H1: μ ≠ 0.316。 東京の 2023 年の高齢化率は約 0.228 で 47 都道府県中最も低く、 平均から約 2.6 標準偏差(s ≈ 0.033)下方に位置する。 SSDSE-B-2026 の年度別データで複数年の検定も可能。
SSDSE-B-2026 は 都道府県別社会経済データ集 2026 年版で、 47 都道府県 × 約 10 年度 × 100 超の指標を含む公的データです。 仮説検定の概念を SSDSE-B-2026 で実証することで、 「数値の動きが地理的・社会的直感と整合するか」を検証できます。
| 列コード | 意味 | 本ページでの用途 |
|---|---|---|
A1101 | 総人口 | 県別人口の差の検定 |
A1303 | 65 歳以上人口 | 高齢化率の地域差検定 |
E1101 | 幼稚園数 | 教育リソースの差検定 |
F3101 | 新規求職申込件数(一般) | 労働市場の地域差検定 |
合成データではなく、 公的統計を念頭に仮説検定の具体的手順を数値で示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # データ:47 都道府県の平均寿命(仮想値、 実際は男女別や年により異なる) 東日本(北海道〜三重 24 都道県):平均 = 84.3、 標準偏差 = 0.7、 N = 24 西日本(滋賀〜沖縄 23 府県):平均 = 84.8、 標準偏差 = 0.6、 N = 23 # 仮説 H₀: μ_東 = μ_西 H₁: μ_東 ≠ μ_西(両側) # t 統計量(Welch) 標準誤差 SE = sqrt(0.7²/24 + 0.6²/23) = sqrt(0.0204 + 0.0157) = sqrt(0.0361) ≈ 0.190 t = (84.3 - 84.8) / 0.190 ≈ -2.63 df ≈ 44.5(Welch 補正) # p 値(両側) p = 2 · P(T < -2.63) ≈ 0.012 # 結論:α = 0.05 で H₀ を棄却 # 「西日本の方が東日本より平均寿命が長い」と統計的に有意 |
1 2 3 4 5 6 7 8 9 10 11 12 | # プールされた標準偏差 s_pool = sqrt(((24-1)·0.7² + (23-1)·0.6²) / (24+23-2)) = sqrt((23·0.49 + 22·0.36) / 45) = sqrt((11.27 + 7.92) / 45) = sqrt(0.426) ≈ 0.653 # Cohen's d d = |84.3 - 84.8| / 0.653 ≈ 0.766 # Cohen の基準: # 0.2 → 小、 0.5 → 中、 0.8 → 大 → 効果量は「中〜大」、 実質的にも意味のある差 |
1 2 3 4 5 6 7 | # 平均差の 95% 信頼区間 平均差 = 84.3 - 84.8 = -0.50 t(0.025, 44.5) ≈ 2.014 95% CI = -0.50 ± 2.014·0.190 = [-0.883, -0.117] # 0 を含まないので p < 0.05 と整合 # 「西日本の平均寿命は東日本より 0.12〜0.88 年長い(95% 信頼)」 |
1 2 3 4 5 6 7 | # 目標:効果量 d = 0.5、 α = 0.05(両側)、 検出力 1−β = 0.80 # 公式:n = 2·(z_{α/2} + z_β)²/d² n = 2·(1.96 + 0.84)²/0.5² = 2·7.84/0.25 ≈ 63 → 各群 63 件、 計 126 件のサンプルが必要 # z 近似の値。t 分布に基づく厳密計算(statsmodels)では各群 ≈ 64 |
# 47 都道府県の総当たり t 検定
ペア数 = 47·46/2 = 1081
# 単純に α = 0.05 のままだと
偽陽性の期待数 = 1081 × 0.05 ≈ 54 件
# Bonferroni 補正
α_補正 = 0.05/1081 ≈ 4.6×10⁻⁵
→ p < 4.6×10⁻⁵ のペアだけ有意
# Holm-Bonferroni / BH 法ならもう少し緩やか
SSDSE-B-2026(公的統計の社会・教育系データセット、 47 都道府県 × 10 年分超 × 100 以上の列)を用いて、 「仮説検定」を体感します。 ファイル名は SSDSE-B-2026.csv、 読み込みは下記の Python コードで行います。
1 2 3 4 5 6 7 8 | import pandas as pd # SSDSE-B-2026 を読み込む(cp932 / Shift_JIS) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='cp932') print(df.shape) # (564, 112) print(df['SSDSE-B-2026'].unique()) # 含まれる年度 latest = df[df['SSDSE-B-2026'] == df['SSDSE-B-2026'].max()].copy() print(latest[['Prefecture', 'A4101', 'A1101']].head()) |
ここで使った中心列 A4101 は SSDSE-B-2026 における出生数(人)です。 例えば 2023 年に人口上位 10 県とそれ以外で出生数の平均を Welch の t 検定で比較すると t = 5.74、 p ≈ 0.0003(実測値)となります。 算出例:
A4101 平均と標準偏差を求めるA4101 と A1101 の相関(線形・順位)を比較する合成データで H₀: μ=50 を Z 検定で評価する。
1 2 3 4 5 6 7 | from scipy.stats import norm xbar, mu0, sigma, n = 53, 50, 10, 100 se = sigma / n**0.5 Z = (xbar - mu0) / se p = 2 * (1 - norm.cdf(abs(Z))) print(f"Z = {Z}") print(f"p = {p:.4f}") |
💬 手計算 (Step 2) Z=3.0 / p≈0.0027 と Python 出力が完全一致。
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 34 | import pandas as pd # ── この抜粋だけで動くように、47 都道府県・最新年度を読み込む ── _d = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) _d = _d[_d['SSDSE-B-2026'] == 2023] from scipy import stats # SSDSE-B に「平均寿命」の列は無いので、実在する列で同じ検定をやってみる。 # ここでは高齢化率を東日本 / 西日本で比べる _east_pref = ['北海道','青森県','岩手県','宮城県','秋田県','山形県','福島県', '茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県', '新潟県','富山県','石川県','福井県','山梨県','長野県','岐阜県', '静岡県','愛知県'] df = _d.copy() df['region'] = df['Prefecture'].apply(lambda p: 'east' if p in _east_pref else 'west') df['高齢化率'] = df['A1303'] / df['A1101'] * 100 east = df[df['region'] == 'east']['高齢化率'] west = df[df['region'] == 'west']['高齢化率'] # 1 標本 t 検定(全国平均 29% と違うか) t1, p1 = stats.ttest_1samp(east, popmean=29.0) print(f'1 標本 t: t={t1:.3f}, p={p1:.4f}') # 2 標本 t 検定(Welch、 等分散非仮定) t2, p2 = stats.ttest_ind(east, west, equal_var=False) print(f'Welch t: t={t2:.3f}, p={p2:.4f}') # 対応のある t 検定(同じ県の 2012 年と 2023 年を比べる) _all = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) _all['aging'] = _all['A1303'] / _all['A1101'] * 100 _p = _all.pivot_table(index='Prefecture', columns='SSDSE-B-2026', values='aging') t3, p3 = stats.ttest_rel(_p[2023], _p[2012]) print(f'対応のある t: t={t3:.3f}, p={p3:.4g}') |
1 2 3 4 5 6 7 8 9 10 | import statsmodels.stats.api as sms from statsmodels.stats.weightstats import ttest_ind # Welch t 検定(自由度・p 値・統計量を取得) t, p, df_ = ttest_ind(east, west, usevar='unequal') print(f't={t:.3f}, p={p:.4f}, df={df_:.2f}') # 平均差の信頼区間 cm = sms.CompareMeans.from_data(east, west) print(cm.tconfint_diff(usevar='unequal')) |
1 2 3 4 5 | import pingouin as pg result = pg.ttest(east, west, paired=False, correction='auto') print(result) # T, dof, alternative, p-val, CI95%, cohen-d, BF10, power まで一括出力 |
1 2 3 4 5 6 7 8 9 10 11 | from statsmodels.stats.power import TTestIndPower analysis = TTestIndPower() # 効果量 d=0.5、 α=0.05、 power=0.8 で必要 N n = analysis.solve_power(effect_size=0.5, alpha=0.05, power=0.80) print(f'各群必要 N = {n:.1f}') # 既知の N で検出力 power = analysis.solve_power(effect_size=0.3, alpha=0.05, nobs1=50, ratio=1) print(f'検出力 = {power:.3f}') |
1 2 3 4 5 6 7 8 9 10 | from statsmodels.stats.multitest import multipletests p_values = [0.001, 0.012, 0.034, 0.048, 0.06, 0.10, 0.20] # Bonferroni rej, p_adj, _, _ = multipletests(p_values, method='bonferroni') print('Bonferroni 補正後 p:', p_adj) # Benjamini–Hochberg rej_bh, p_bh, _, _ = multipletests(p_values, method='fdr_bh') print('BH 補正後 p:', p_bh) |
1 2 3 4 5 6 7 8 9 | from statsmodels.stats.weightstats import ttost_ind # 同等性の閾値 ±0.5 # ttost_ind は (全体の p, 下側検定の (t, p, df), 上側検定の (t, p, df)) を返す p_all, lower, upper = ttost_ind(east, west, low=-0.5, upp=0.5) print(f'TOST p(全体)= {p_all:.4f}') print(f'TOST p(下限)= {lower[1]:.4f}') print(f'TOST p(上限)= {upper[1]:.4f}') # 両方 < 0.05 なら「同等」と結論 |
1 2 3 4 5 6 7 | from scipy.stats import permutation_test def diff_means(x, y): return x.mean() - y.mean() res = permutation_test((east, west), diff_means, n_resamples=10000, alternative='two-sided') print(f'順列検定 p={res.pvalue:.4f}') |
scipy / pandas / scikit-learn / statsmodels を中心とした標準的な実装例です。 まず CSV を読み込み、 次に 仮説検定 の解析を行います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import pandas as pd import numpy as np from scipy import stats df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='cp932') df = df[df['SSDSE-B-2026'] == df['SSDSE-B-2026'].max()].copy() x = df['A4101'].astype(float).values y = df['A1101'].astype(float).values # 基本統計量 print('n =', len(x)) print('mean(x) =', np.mean(x)) print('std(x) =', np.std(x, ddof=1)) # 仮説検定 の代表的計算(用途に応じて scipy/statsmodels を切替える) r, p = stats.pearsonr(x, y) print(f'Pearson r = {r:.4f}, p = {p:.4g}') rs, ps = stats.spearmanr(x, y) print(f'Spearman rho = {rs:.4f}, p = {ps:.4g}') |
用途別の追加実装:
1 2 3 4 5 6 7 8 9 | # 標準化と簡易クラスタリングの例 from sklearn.preprocessing import StandardScaler from sklearn.cluster import KMeans X = df[['A4101', 'A1101']].astype(float).values Xs = StandardScaler().fit_transform(X) km = KMeans(n_clusters=4, n_init=10, random_state=0).fit(Xs) df['cluster'] = km.labels_ print(df[['Prefecture', 'A4101', 'A1101', 'cluster']].head(10)) |
1 2 3 4 5 6 7 | # 時系列(北海道の A4101)— 例として ARIMA 系の前処理 import statsmodels.api as sm ts = df.sort_values('SSDSE-B-2026').groupby('SSDSE-B-2026')['A4101'].mean() print(ts.tail()) res = sm.tsa.stattools.adfuller(ts) print('ADF stat:', res[0], 'p:', res[1]) |
以下は SSDSE-B-2026 を題材にした実コード例集です。 すべて data/raw/SSDSE-B-2026.csv を読み込み、 実値で動作確認しています。
1 2 3 4 5 6 7 8 | import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) d23 = df[df['SSDSE-B-2026']==2023].reset_index(drop=True) d23['aging'] = d23['A1303'].astype(float)/d23['A1101'].astype(float) d23['birth_rate'] = d23['A4101'].astype(float)/d23['A1101'].astype(float)*1000 print(d23[['Prefecture','aging','birth_rate']].describe().round(3)) print('最高齢化:', d23.nlargest(3,'aging')[['Prefecture','aging']].values) print('最低高齢化:', d23.nsmallest(3,'aging')[['Prefecture','aging']].values) |
1 2 3 4 5 6 7 8 9 10 11 | import pandas as pd import matplotlib.pyplot as plt df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) d23 = df[df['SSDSE-B-2026']==2023].reset_index(drop=True) d23['aging'] = d23['A1303'].astype(float)/d23['A1101'].astype(float) fig, axes = plt.subplots(1, 2, figsize=(12, 4)) axes[0].hist(d23['aging'], bins=15, edgecolor='black') axes[0].set_xlabel('高齢化率'); axes[0].set_ylabel('県数') axes[1].boxplot(d23['aging']) axes[1].set_ylabel('高齢化率') plt.savefig('aging_dist.png', dpi=100) |
1 2 3 4 5 6 7 8 9 10 11 12 | import pandas as pd from scipy import stats import numpy as np df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) d23 = df[df['SSDSE-B-2026']==2023].copy() d23['aging'] = d23['A1303'].astype(float)/d23['A1101'].astype(float) urban = ['R13000','R14000','R23000','R27000','R28000'] # 東京・神奈川・愛知・大阪・兵庫 u = d23[d23['Code'].isin(urban)]['aging'] r = d23[~d23['Code'].isin(urban)]['aging'] t, p = stats.ttest_ind(u, r, equal_var=False) d_cohen = (u.mean() - r.mean()) / np.sqrt((u.var() + r.var())/2) print(f't = {t:.2f}, p = {p:.4f}, Cohen d = {d_cohen:.2f}') |
1 2 3 4 5 | import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df['aging'] = df['A1303'].astype(float)/df['A1101'].astype(float) trend = df.groupby('SSDSE-B-2026')['aging'].agg(['mean','std','min','max']).round(3) print(trend) |
仮説検定は前提条件次第で意味が変わります。 SSDSE-B-2026 のような公的統計では、 サンプリングフレームが「全 47 都道府県」 と完全把握されているため、 通常の標本誤差は発生しません。 しかし「2023 年の 1 時点を全体集団とみなすか、 もっと長期の集団からの 1 サンプルとみなすか」で解釈が変わります。
SSDSE-B-2026 のような 100 超の列を扱うと、 多重比較(同じデータで多数の検定を行う)の罠が発生します。 Bonferroni 補正、 Benjamini-Hochberg などで補正してから 仮説検定に関連する統計量を解釈すべきです。
都道府県の中に市区町村があり、 階層構造を持つ場合、 階層線形モデル(HLM)で 仮説検定を扱うことを検討します。 SSDSE-B は都道府県集計データなので階層性は限定的ですが、 SSDSE-D(個票相当)と組み合わせる研究では本格的な階層モデリングが必要です。
SSDSE-B-2026 は 2012〜2023 年の 12 年間のパネル構造を持ちます。 仮説検定を時間軸込みで扱うときは、 固定効果モデル・ランダム効果モデルなどパネルデータ手法を併用します。
SSDSE-B-2026 の県別データから「仮説検定に関わる関係」を抽出できても、 それは多くの場合「相関」であり、 「因果」を主張するには無作為化試験・自然実験・操作変数などの追加設計が必須です。
| H₀ が真 | H₁ が真 | |
|---|---|---|
| H₀ を棄却 | 第I種誤り(α, false positive) | 正しい判定(検出力 1-β) |
| H₀ を棄却せず | 正しい判定 | 第II種誤り(β, false negative) |
$\alpha$ を厳しくすると(小さくすると)第I種誤りは減るが、 第II種誤りは増える(トレードオフ)。 両方を同時に下げるにはサンプルサイズ $n$ を増やすしかない。
「H₁ が真のときに、 正しく H₀ を棄却する確率」。 通常 $1-\beta = 0.80$ を目標。
検出力は 4 要素で決まる:
1 2 3 4 5 6 7 8 9 10 11 | from statsmodels.stats.power import TTestIndPower analysis = TTestIndPower() # n を逆算(効果量 d=0.5、 α=0.05、 検出力 0.80) n = analysis.solve_power(effect_size=0.5, alpha=0.05, power=0.80) print(f'必要 n = {int(n)}') # 各群 ≈ 64 # 与えられた n での検出力 power = analysis.solve_power(effect_size=0.3, nobs1=50, alpha=0.05) print(f'検出力 = {power:.3f}') |
p 値は効果の大きさではなく、 「H₀ の下でデータが出現する稀少さ」を表す指標です。 サンプルサイズが大きければ、 ごくわずかな差でも p < 0.001 になります。 例:N=10000 で平均差 0.01 でも有意になりますが、 実務的に意味があるかは別問題。 必ず効果量(Cohen's d、 r、 η²)と信頼区間を併報してください。 ASA(米国統計学会)も 2016 年に同様の声明を発表しています。
p > 0.05 は「H₀ を棄却できない」という意味で、 「H₀ が正しい」ことを示すわけではない。 サンプルサイズが小さく検出力が不足している可能性、 効果量が小さくても実在する可能性が残ります。 「差がない」と主張したいなら、 同等性検定(TOST: Two One-Sided Tests)や事前のサンプルサイズ設計が必要です。
変数を変える、 サブグループを変える、 サンプルを足す、 外れ値を除外する……を有意になるまで繰り返すのは p-hacking の典型。 こうした「研究者の自由度」の悪用は再現性危機の主因とされます。 対策は事前登録(preregistration)、 分析計画の文書化、 多重比較補正の徹底。 Bayes factor のように証拠の強さを連続的に評価する手法も有効です。
20 個の独立な検定を α = 0.05 で行うと、 少なくとも 1 つが偽陽性になる確率は 1 − (1−0.05)²⁰ ≈ 64%。 47 都道府県の全ペア比較なら 1081 検定で偽陽性 54 件が期待される。 family-wise error rate を抑える Bonferroni 法、 Holm 法、 FDR を抑える Benjamini–Hochberg 法を、 状況に応じて使い分けてください。
同じデータで両側検定が p = 0.08、 片側にすると p = 0.04 で「有意!」と書くのは不当な操作です。 片側検定はデータを見る前に「方向性が確定している」場合のみ許されます。 「効果はあるはずだ」と思って片側にしたら、 仮説検定の枠組みが壊れます。 事前登録で方向性を明示することが必須です。
t 検定、 ANOVA、 F 検定など多くのパラメトリック検定は正規性・等分散性を前提とします。 中心極限定理で N が大きければ正規性は緩和されますが、 N が小さく分布が歪んでいると Type I エラーが狂います。 QQ プロット、 Shapiro–Wilk、 Levene 検定で確認し、 必要なら Wilcoxon、 Kruskal–Wallis、 順列検定などノンパラ手法に切り替えましょう。
論文・レポートで「p < 0.05 なので有意」とだけ書くのは不十分。 効果量、 信頼区間、 サンプルサイズ、 検出力、 検定の前提、 多重比較補正の有無を併報する必要があります。 ASA は「具体的に何が分かったか」を述べることを推奨。 「中程度の効果(d=0.5, 95% CI: 0.3-0.7、 N=100、 power 0.80)」のように書きましょう。
仮説検定 を実務で扱う際に踏みやすい落とし穴を 5 件挙げます。
仮説検定は推測統計の中心概念で、 標本から母集団の特性を確率的に判断する枠組み。 推定・モデル選択・効果量と密接に連携する。
「p < 0.05 だから有意」と機械的に判断するのは危険。 p 値は「効果がゼロ」と仮定したときに観測データが得られる確率であり、 効果の大きさや実用的意味とは別物。 効果量と信頼区間も併せて報告する。
| 目的 | データ型 | パラメトリック | ノンパラメトリック |
|---|---|---|---|
| 1群の平均を仮説値と比較 | 連続 | 1標本 t検定 | Wilcoxon 符号付順位 |
| 対応のある 2群比較 | 連続 | 対応のある t検定 | Wilcoxon 符号付順位 |
| 独立 2群比較 | 連続 | 2標本 t検定 / Welch | Mann-Whitney U |
| 3群以上の平均 | 連続 | ANOVA | Kruskal-Wallis |
| 分散の同等性 | 連続 | F検定 / Levene | Bartlett |
| カテゴリ × カテゴリ | 離散 | χ²検定 | Fisher の正確検定(小サンプル) |
| 相関の有意性 | 連続 × 連続 | Pearson の t検定 | Spearman / Kendall |
頻度主義の p値の問題点を克服する、 ベイズ統計の対案。 「H₁ が H₀ より何倍ありそうか」を直接示す。
$$ BF_{10} = \frac{P(\text{data} \mid H_1)}{P(\text{data} \mid H_0)} $$
| BF₁₀ | 証拠の強さ(Kass-Raftery) |
|---|---|
| 1 〜 3 | 弱い・「言うほどでもない」 |
| 3 〜 20 | 中程度(positive) |
| 20 〜 150 | 強い |
| > 150 | 非常に強い |
近年の論文では p値とベイズファクターを併記するケースが増加。 ベイズ流の利点:「H₀ も支持できる」(p値では不可能)。
| ❌ 誤解 | ✅ 正しい理解 |
|---|---|
| p値が小さい = 効果が大きい | サンプルサイズが大きいだけかもしれない。 効果量で評価 |
| p > 0.05 = 差はない | 「証拠不十分」。 検出力不足の可能性 |
| p値だけ報告すれば十分 | 点推定 + CI + 効果量 + p値 + n を全部 |
| データを見てから片側検定にする | p-hacking。 事前登録が必要 |
| 複数検定を補正なしで実施 | Bonferroni / BH-FDR で補正 |
| 有意になるまでサンプルを増やす | 事前にサンプルサイズを決める |
| p値が再現性を保証する | 「再現性危機」の問題。 複数研究の蓄積が必要 |
⚠️ ASA 声明(2016)の 6原則:(1) p値は仮説と観測データの不一致を測る、 (2) 「H₀ が真である確率」ではない、 (3) p < 0.05 だけで結論を出さない、 (4) 完全な報告と透明性が必要、 (5) p値は効果の大きさを測らない、 (6) p値だけでモデルの良さは分からない。
誤り。 p値は「H₀ を所与とした上で、 観測データ以上に極端なデータが出る条件付き確率」。 ベイズの定理を使わなければ「H₀ が真である確率」は計算できない。
1 2 3 | from statsmodels.stats.power import TTestIndPower n = TTestIndPower().solve_power(effect_size=0.5, alpha=0.05, power=0.8) print(int(n)) # 約 64 |
サンプルサイズが大きすぎると、 ほぼゼロの差でも p値は小さくなる(CLT のため)。 効果量(Cohen's d)を見て、 1cm の差が実用上意味を持つか判断する。 p値の罠の典型例。
多重比較問題。 20 × 19 / 2 = 190 ペアの検定。 偶然 1 個有意になるのは予想範囲(190 × 0.05 ≈ 9.5 個の偽発見が期待される)。 Bonferroni / BH-FDR で補正、 または事前登録した仮説のみ検定する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import pandas as pd from scipy import stats df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932') data = df.iloc[1:].copy() data['年度'] = data['SSDSE-B-2026'] d23 = data[data['年度']=='2023'] food = pd.to_numeric(d23['L322101'], errors='coerce') / 1000 east_pref = ['北海道','青森県','岩手県','宮城県','秋田県','山形県','福島県', '茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県', '新潟県','富山県','石川県','福井県','山梨県','長野県','岐阜県','静岡県','愛知県','三重県'] east = food[d23['Prefecture'].isin(east_pref)] west = food[~d23['Prefecture'].isin(east_pref)] t, p = stats.ttest_ind(east.dropna(), west.dropna(), equal_var=False) # Welch print(f't = {t:.3f}, p = {p:.4f}') # 効果量も d = (east.mean() - west.mean()) / pd.concat([east, west]).std() print(f"Cohen's d = {d:.3f}") |
「東日本と西日本の食料費(2023 年、 SSDSE-B-2026 の L322101)平均の差を Welch の t 検定で検証した。 結果は東日本の平均(82.8 千円, $s$=6.0, $n$=24)、 西日本の平均(78.3 千円, $s$=4.7, $n$=23)で、 統計的に有意な差が認められた($t(43.3)=2.84, p=.007$, Cohen's $d$=0.82, 差の 95% CI [1.3, 7.7] 千円)。 効果量は大きく実質的にも意味のある差といえる。 ただしサンプルサイズ($n=47$)から検出力解析を行うと、 d=0.5 程度の中効果を検出力 80%($1-\beta=0.80$)で検出するには各群 64 必要であり、 より小さな効果については検出力不足の可能性がある。」
必須要素:(1) 使用した検定名、 (2) 検定統計量と自由度、 (3) p値、 (4) 効果量、 (5) 信頼区間、 (6) 検出力、 (7) サンプルサイズ。
| 関係 | 概念 | 仮説検定との接続 |
|---|---|---|
| 上位(一般化) | 統計推論一般 | 仮説検定は推論の構成要素 |
| 下位(特殊化) | 特定の検定・推定 | 仮説検定の応用 |
| 並列(兄弟) | 関連手法 | 同じ問題への別アプローチ |
| 前提 | 確率分布・標本 | 仮説検定の数学的基礎 |
| 応用 | 政策評価・施策効果測定 | SSDSE-B-2026 のような公的統計での実務 |
SSDSE-B-2026 で「人口」「出生数」「死亡数」を比較。 仮説検定を使って自然増減のパターンを定量化。 東京・神奈川・愛知の都市集中、 秋田・高知の過疎化。
「幼稚園数 (E1101)」「大学数 (E6102)」「高等学校生徒数 (E4501)」を 仮説検定で分析。 県別の教育リソース配分を評価。 都市と地方の格差を可視化。
「一般診療所数 (I5102)」「一般病院数 (I510120)」「高齢化率 (A1303/A1101)」 を組み合わせ。 仮説検定で医療資源の地域不均衡と高齢化の関係を推定。
「新規求職申込件数 (F3101)」「延べ宿泊者数 (G7101)」「消費支出 (L3221)」を 仮説検定で関連付け。 観光業県と都市県のパターン差。
「高齢化率 (A1303/A1101)」「婚姻件数 (A9101)」「合計特殊出生率 (A4103)」を 仮説検定で評価。 高齢化が進む県の人口動態を定量化。 県政策への含意。
研究結果を 仮説検定を使って報告するときに守るべきチェックリスト:
仮説検定は学術研究だけでなく、 政策・ビジネスの意思決定に直接活用されています。
計量経済学・教育測定・心理測定・疫学などで 仮説検定は基礎ツール。 近年は機械学習との融合で新しい応用が広がっています。
仮説検定 の概念は、 統計学の発展史と並行して洗練されてきました。
日本では、 1947 年の統計法制定以降、 SSDSE-B のような公的統計の整備が進み、 仮説検定を学ぶ実データ環境が充実してきました。
仮説検定の真の力は 「同じ問いに対して 6 種類の検定でどれだけ結果が一致するか」を確認できる 点にある。 一致すれば結論は頑健、 大きく食い違えばどこかの仮定が破れている。 ここでは SSDSE-B-2026 の高齢化率を「東日本 (24 都道府県)」と「西日本 (23 都道府県)」に分け、 6 種類のテストで比較する。 これは結果の解釈にとどまらず、 p 値・有意水準・効果量・検出力の意味を実感する最良の実習でもある。
📥 入力データ: SSDSE-B-2026 から「65 歳以上人口 / 総人口」で高齢化率を算出し、 東日本 / 西日本でグルーピング。
このコードでやること: 同一データに対して (1) 対応なし t 検定、 (2) Welch の t 検定、 (3) Mann-Whitney U、 (4) ブートストラップ、 (5) 順列検定、 (6) ベイズ的事後確率の 6 種を一気に実行し、 結論の安定性を確認する。
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 34 35 36 37 38 39 40 41 42 | import pandas as pd, numpy as np from scipy.stats import ttest_ind, mannwhitneyu df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='cp932') df = df[df['SSDSE-B-2026']==2023].copy() df['高齢化率'] = df['A1303'] / df['A1101'] # 65歳以上人口 / 総人口 east = ['北海道','青森県','岩手県','宮城県','秋田県','山形県','福島県','茨城県','栃木県','群馬県', '埼玉県','千葉県','東京都','神奈川県','新潟県','富山県','石川県','福井県','山梨県','長野県','岐阜県','静岡県','愛知県','三重県'] df['区分'] = df['Prefecture'].apply(lambda p: '東日本' if p in east else '西日本') a = df.loc[df['区分']=='東日本','高齢化率'].values b = df.loc[df['区分']=='西日本','高齢化率'].values # 1. Student t (等分散仮定) t1, p1 = ttest_ind(a, b, equal_var=True) # 2. Welch t (不等分散) t2, p2 = ttest_ind(a, b, equal_var=False) # 3. Mann-Whitney U (ノンパラ) u, p3 = mannwhitneyu(a, b, alternative='two-sided') # 4. Bootstrap mean difference 95%CI rng = np.random.default_rng(2026) boot = [np.mean(rng.choice(a, size=len(a), replace=True)) - np.mean(rng.choice(b, size=len(b), replace=True)) for _ in range(10000)] ci_lo, ci_hi = np.percentile(boot, [2.5, 97.5]) # 5. Permutation p (mean diff) obs = a.mean() - b.mean() combined = np.concatenate([a,b]) perm = [] for _ in range(10000): rng.shuffle(combined) perm.append(combined[:len(a)].mean() - combined[len(a):].mean()) p5 = np.mean(np.abs(perm) >= abs(obs)) # 6. Cohen's d 効果量 d = obs / np.sqrt(((len(a)-1)*a.var(ddof=1) + (len(b)-1)*b.var(ddof=1)) / (len(a)+len(b)-2)) print(f'平均: 東 {a.mean():.4f} vs 西 {b.mean():.4f} (差 {obs:+.4f})') print(f'Student t p={p1:.4f}') print(f'Welch t p={p2:.4f}') print(f'Mann-Whitney p={p3:.4f}') print(f'Bootstrap 95% CI: [{ci_lo:+.4f}, {ci_hi:+.4f}]') print(f'Permutation p={p5:.4f}') print(f"Cohen's d ={d:.3f} (|d|>0.5 で中程度効果)") |
📤 実行例:
💬 結果の読み方: 6 種の検定すべてが「東西で有意差なし」 (p > 0.05) で一致。 さらに 95% CI が 0 を含み、 効果量も |d| ≈ 0.26 と「小さい」水準。 ここまで一致すれば結論は頑健で、 「日本の高齢化は地域差ではなく全国共通の構造問題」と説明できる。 もし 6 検定の結果が割れたら、 (1) 外れ値が片方の検定だけに効いている、 (2) 分布が極端に歪んでいる、 (3) サンプルサイズが小さく検出力不足 — のいずれかを疑う。 各検定の使い分けは t 検定 ・ ノンパラメトリック検定、 および 本ページの検定表 へ。
| 検定 | 前提 | 外れ値耐性 | 小標本適否 |
|---|---|---|---|
| Student t | 正規性 + 等分散 | 弱い | N=30 以上推奨 |
| Welch t | 正規性のみ (分散異 OK) | 弱い | N=30 以上推奨 |
| Mann-Whitney U | 独立性のみ | 強い | N=5 でも可 |
| Bootstrap CI | i.i.d. | 中程度 | N≥10 で目安 |
| Permutation | 交換可能性 | 強い | N=5 でも厳密 |
| Cohen's d (記述) | 検定ではなく効果量 | 弱い | N 非依存 |
仮説検定の枠組みは 20 世紀初頭に Fisher・Neyman・Pearson が確立した。 Fisher は「p 値による証拠の強さ評価」、 Neyman-Pearson は「α/β 誤りを制御する意思決定」 を主張し、 両者は哲学的に異なる。 現代の実務では両者がハイブリッド (p < 0.05 を「有意」と呼ぶ慣習) で使われているが、 2016 年 ASA (米国統計学会) が公式声明で「p 値だけでは結論を出すな」と警告。 2019 年には Nature 誌が「統計的有意性を引退させよう」 (Amrhein et al.) を掲載するなど、 検定の 誤用への警鐘 が強まっている。
このコードでやること: SSDSE-B-2026 から 20 個の指標を取り出し、 全ての対で相関係数の p 値を計算する。 多重比較補正なしでは false discovery が高頻度で起きることを実証。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import pandas as pd, numpy as np from scipy.stats import pearsonr from itertools import combinations df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='cp932') df = df[df['SSDSE-B-2026']==2023].copy() numeric_cols = df.select_dtypes(include=[np.number]).columns.drop('SSDSE-B-2026')[:20] # 年度列を除く先頭 20 列 # 全 20C2 = 190 対の p 値を計算 pvals, sig_pairs = [], [] for c1, c2 in combinations(numeric_cols, 2): _, p = pearsonr(df[c1].dropna(), df[c2].dropna()) pvals.append(p) if p < 0.05: sig_pairs.append((c1, c2, p)) print(f'検定数: {len(pvals)}') print(f'p < 0.05 の対: {len(sig_pairs)} ({len(sig_pairs)/len(pvals)*100:.1f}%)') print(f'帰無仮説下の期待値 (5%): {len(pvals)*0.05:.1f} 対') # Bonferroni 補正後 threshold = 0.05 / len(pvals) sig_bonf = sum(1 for p in pvals if p < threshold) print(f'Bonferroni 補正後 (α={threshold:.5f}): {sig_bonf} 対') |
📤 実行例:
💬 結果の読み方: 190 個の検定で「p < 0.05」のペアが 190 (100%) も。 これは先頭 20 列がいずれも人口関連指標で 本質的に強相関 (人口規模経由) しているためだが、 もし無作為データなら 9.5 個程度しか出ないはず。 多重比較を意識せずに「有意な相関を見つけた!」と報告すると p-hacking になる。 Bonferroni 補正でも 188 個残るが、 これは効果量も併記すべき。 関連: 有意水準、 効果量。
| 問題タイプ | データ条件 | 推奨検定 |
|---|---|---|
| 1 群平均が μ₀ と違うか | 正規性 / N>30 | one-sample t test |
| 同上 | 非正規 / 小標本 | Wilcoxon signed-rank |
| 2 群平均比較 | 独立 + 等分散 | Student t |
| 2 群平均比較 | 独立 + 不等分散 | Welch t |
| 2 群比較 | 対応あり | paired t test |
| 2 群比較 | ノンパラ | Mann-Whitney U |
| 3+ 群比較 | 正規 + 等分散 | ANOVA |
| 3+ 群比較 | ノンパラ | Kruskal-Wallis |
| カテゴリ独立性 | 2x2 大標本 | χ² 検定 |
| カテゴリ独立性 | 小標本 | Fisher 正確検定 |
| 2 連続変数の関連 | 線形 | Pearson 相関 |
| 2 連続変数の関連 | 単調 / 順序 | Spearman ρ, Kendall τ |
仮説検定の結果を論文・レポートにまとめる際の最低要件をまとめる。 SSDSE-B-2026 を題材とした研究レポートでも以下の項目を全て埋めることで、 査読・社内レビューでの指摘を大幅に減らせる。
上記 10 項目はすべて満たすことで、 査読者・社内レビュアー・将来の自分自身からの「あの結果は信頼できない」 という指摘を確実に防げる。 SSDSE-B-2026 のような小規模 (N=47) データでも、 報告の形式は大規模研究と同じ。 むしろサンプルが少ない分、 効果量と信頼区間の併記は必須となる。 また「事前 (pre-registration) と事後分析の区別」を明示することで、 探索的研究と確証的研究を分離できる。 これは Open Science Framework (OSF) などの仕組みで近年標準化が進んでいる潮流である。 SSDSE-B-2026 ベースの研究レポートも、 同じ形式 (事前登録 → データ収集 → 検定 → 報告) を踏襲することで、 統計学的にも倫理的にも妥当な研究として認められる。
本節は p 値、 有意水準、 t 検定、 ANOVA、 信頼区間、 標準誤差、 効果量、 対立仮説、 帰無仮説、 標本 と相互参照。
仮説検定の失敗の大半は「実行コードのバグ」ではなく、 事前準備の不備か解釈の暴走で起こる。 本補講では SSDSE-B-2026 都道府県データの「都市/地方の高齢化率の差」を題材に、 事前準備→実行→解釈の 3 フェーズで具体的なチェック項目をまとめる。 単なる p 値の読み方ではなく、 「設計時点で何を決めておかなければならないか」「どう報告すれば再現可能か」を点検する。
| 項目 | 確認内容 | 未達時の影響 |
|---|---|---|
| 仮説の事前登録 | H0 / H1 を文書化、 片側か両側か明示 | 事後仮説化 (HARKing) |
| 有意水準 | α = 0.05 か 0.01 か、 多重比較補正の方針 | 事後 α 引下げで偽陽性増 |
| 検定統計量と分布 | t / F / χ² / U など、 自由度 | 分布前提違反 |
| 前提条件 | 正規性、 等分散性、 独立性 | p 値の解釈不能 |
| サンプルサイズ | 事前 power 解析、 必要 n を算出 | 過小 → 検出力不足、 過大 → 実質的でない差を検出 |
| 効果量の目標値 | Cohen d、 r、 η² など報告必須 | 「統計的有意」と「実質的有意」の混同 |
equal_var=False) をデフォルトにしておくと、 等分散性に依存しない結果が得られる。 古典的 Student の t 検定はサンプルサイズが大きく異なる場合に偏る。scipy.stats.shapiro や normaltest を併用。 n < 30 で外れ値があるならノンパラメトリックも検討。| 結果パターン | 適切な結論文 | NG 文例 |
|---|---|---|
| p < α かつ効果量 大 | 「差は統計的・実質的に有意」 | 「H0 を完全に棄却した」 |
| p < α かつ効果量 小 | 「統計的有意だが実質差は小さい」 | 「有意な差があった」 (差の大きさ未報告) |
| p ≥ α | 「差を検出できなかった」 | 「H0 を採択した」「差がないと証明」 |
| p ≈ α (境界) | 「再検証が必要」と明記、 信頼区間で評価 | 「ほぼ有意」「marginally significant」を多用 |
| 状況 | 推奨検定 | 代替 (前提違反時) |
|---|---|---|
| 2 群平均の差 (独立) | Welch t 検定 | 並べ替え検定、 順位和検定 |
| 2 群平均の差 (対応あり) | 対応のある t 検定 | 符号付順位検定 |
| 3 群以上の平均 | 一元配置 ANOVA | Kruskal-Wallis (順位ベース) |
| 分割表 (頻度) | χ² 独立性検定 | Fisher の正確検定 (期待度数 < 5) |
| 比率の差 | 2 比率の z 検定 | Fisher、 ベイズ推定 |
| 時系列の傾向 | 回帰係数の検定 | Mann-Kendall (順位ベース) |
本補講は p 値、 有意水準、 t 検定、 ANOVA、 信頼区間、 標準誤差、 効果量、 帰無仮説、 対立仮説、 標本、 固定効果モデル ページの内容と一体運用すべき意思決定群を扱う。
「仮説検定(p値・有意水準・検出力・効果量)」を扱う際の手法選択は、 状況に応じて以下のフローで判断すると迷いが減る。
このフローに沿って判断することで、 「仮説検定(p値・有意水準・検出力・効果量)」を中核とした適切な手法選択ができる。
論文記事から各用語のリンクをクリックすると、 該当箇所が開きます:
本文では p 値・α・検出力・効果量の定義と計算を一通り学びました。 この深化セクションでは一段掘り下げて、 「その p 値は、 そもそも何のランダムネスに関する確率なのか」という、 教科書が意外と素通りする問いを考えます。 SSDSE-B-2026 のような「47 都道府県 = 全数データ」を検定するとき、 この問いは避けて通れません。
仮説検定の最も素朴な直感は、 数式より先にシャッフルで掴めます。 練習問題 5 で扱った「東日本 vs 西日本の食料費(L322101、 2023 年)」を思い出してください。 実測では東日本 24 都道県の平均 82.79 千円、 西日本 23 府県の平均 78.31 千円で、 差は 4.48 千円でした。
ここで想像実験をします。 47 都道府県の食料費の値はそのままに、 「東」「西」のラベルだけを無作為に貼り直したら、 4.48 千円以上の差はどのくらいの頻度で偶然生じるでしょうか。 もしラベルを何度シャッフルしてもこれほどの差がめったに出ないなら、 「東西というラベルには食料費と結びついた実質がある」と考えるのが自然です。 逆にシャッフルでも頻繁に出る程度の差なら、 「偶然の範囲」と言われても反論できません。 p 値とは、 この「シャッフルしても出てしまう頻度」を理論分布(t 分布など)で近似したもの—— そう捉えると、 帰無分布・棄却域・極端さといった本文の概念が一本の線でつながります。
落とし穴 1:47 都道府県は「標本」ではない。 t 検定の標準的な物語は「母集団から無作為抽出した標本から母平均を推測する」ですが、 47 都道府県は日本の全都道府県、 つまり全数(母集団そのもの)です。 2023 年の東西の食料費平均に 4.48 千円の差があることは、 検定するまでもなく「事実」として確定しています。 では p = 0.0069 は何を意味するのか。 主な正当化は 2 つあります。 (1) 超母集団(superpopulation)の見方:観測された 47 の値を「社会経済的な確率過程が生成した一つの実現値」とみなし、 その背後の生成過程に東西差があるかを問う。 (2) ランダム化・順列の見方:上の直感のとおり「ラベルの割り付けに対する希少性」を問う。 どちらの立場かで解釈の言葉遣いが変わるため、 レポートでは「東西の構造的な差を示唆する」のように、 何を推測しているかを意識した表現にするのが安全です。
落とし穴 2:年をプールして n を水増しする(疑似反復)。 SSDSE-B-2026 は 2012–2023 年の 12 年分を含むので、 全年をプールすると東日本 n = 288、 西日本 n = 276 になります。 実際に同じ Welch の t 検定を行うと t = 7.698、 p ≈ 6.3 × 10⁻¹⁴(実測)と、 2023 年単年の p = 0.0069 から劇的に「有意」になります。 しかしこれは誤りです。 同じ県の隣り合う年の値は強く似ており(自己相関)、 独立な観測は 564 個もありません。 実質的な情報量は「47 県 × ほぼ 1」に近く、 t 検定の独立性の仮定が崩れています。 実際、 県ごとに 12 年平均を取ってから検定し直すと t = 3.041、 p = 0.0039(実測、 n = 24 + 23)に戻ります。 「観測を増やしたら p が小さくなった」のではなく、 「同じ情報を何度も数えて p を偽装した」—— これは生態学で疑似反復(pseudoreplication)と呼ばれる古典的な誤りで、 パネルデータではクラスタ頑健標準誤差や混合効果モデルで対処します。
直感で述べたシャッフルは、 そのまま順列検定(permutation test)という正式な手法になります。 正規性の仮定を使わず、 ラベルの並べ替えだけから p 値を経験的に構成します。 実際に SSDSE-B-2026 の 2023 年・食料費(L322101、 千円換算)で、 東西ラベルを 10,000 回シャッフル(乱数シード 42 で固定)した結果は次のとおりです(実測):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import pandas as pd, numpy as np df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) d23 = df[df['SSDSE-B-2026'] == 2023] east_pref = ['北海道','青森県','岩手県','宮城県','秋田県','山形県','福島県','茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県','新潟県','富山県','石川県','福井県','山梨県','長野県','岐阜県','静岡県','愛知県','三重県'] food = pd.to_numeric(d23['L322101'], errors='coerce') / 1000 east = food[d23['Prefecture'].isin(east_pref)].dropna().values west = food[~d23['Prefecture'].isin(east_pref)].dropna().values obs = east.mean() - west.mean() # 4.484(実測) rng = np.random.default_rng(42) allv = np.concatenate([east, west]) cnt = 0 for _ in range(10000): perm = rng.permutation(allv) if abs(perm[:24].mean() - perm[24:].mean()) >= abs(obs): cnt += 1 print(cnt / 10000) # 0.0061(seed=42 での実測。 t 検定の p=0.0069 とほぼ一致) |
2 つの p 値(0.0061 と 0.0069)がほぼ一致することは偶然ではありません。 t 検定は「シャッフル分布を数式で近似した近道」であり、 順列検定はその近似を計算機で愚直に置き換えたものだからです。 n が小さい・分布が歪んでいる・外れ値がある場面では順列検定(やブートストラップ)の方が頑健で、 逆に両者が大きく食い違ったら理論検定の仮定を疑うシグナルになります。 なお順列 p 値はシャッフル回数に依存する近似なので、 再現性のために乱数シードと回数の明記(ここでは seed = 42、 B = 10,000)が必須です。