論文一覧に戻る 📚 用語解説(ジャストインタイム型データサイエンス教育)
F検定
F-test (F)
回帰モデルの全体の有意性や、複数群の分散の差を検定。回帰のF統計量は「モデル全体が意味あるか」。
仮説検定FF検定ANOVA

🔖 キーワード索引 — F 検定を多角的に理解する

F 検定(F-test)を確実に理解するための関連キーワードを、難易度別に整理しました。

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

🟡 中級キーワード

🔴 上級キーワード

💡 30秒で分かる結論

🍰 まずはやさしく

ばらつきを比べるための道具です。

グループごとの差があるか調べます。

部活の練習量に差があるか測るようなものです。

ここではF検定の結論を短くまとめます。

👁️ 直感 — F検定は「分散比の検定」

F検定は2つの分散の比を検定する手法。 もっとも頻繁に使う2つの応用:

F分布

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

🍰 まずはやさしく

データ分析でよく使う手法です。

モデル全体に意味があるか判断します。

都道府県のデータ分析などで活用します。

ここではF検定の全体像を詳しく説明します。

論文中に 「F検定」として登場する用語。

F検定 とは:回帰モデルの全体の有意性や、複数群の分散の差を検定。回帰のF統計量は「モデル全体が意味あるか」。

本ページでは F 検定 を扱う。 統計データ分析コンペティション (2026) の教材で、 SSDSE-B-2026 (47 都道府県 × 12 年 × 112 列) の実データを使った再現可能な学習を目指す。

F 検定は統計・データサイエンスの体系における重要概念のひとつ。 本ページは「定義・直感・数式・実装・落とし穴・関連手法」の 6 視点で構成され、 各視点は独立して読めるが順序通り読むと体系的な理解が得られる。

🎨 直感で掴む — F 検定は「分散の天秤」

🍰 まずはやさしく

ばらつきを比べる天秤のようなものです。

2つのグループの差が本物か確かめます。

スマホカメラのブレ具合を比べるイメージです。

ここではF検定の仕組みを直感的に学びます。

F 検定の本質は 「2 つのグループのばらつきを天秤に乗せる」 ことです。 片方の皿に第 1 群の分散、 もう片方に第 2 群の分散を乗せ、 比 $F = s_1^2/s_2^2$ がどれだけ 1 から離れるかを測ります。 比が 1 のあたりなら釣り合っている(等分散)、 大きく外れていれば「両者は違うばらつきを持つ」 という判断です。

もう一つの直感は 「カメラのブレ比較」。 同じ被写体を 2 台のカメラで撮ったとき、 一方の写真の方が大きくブレていれば(分散が大きければ)「カメラの性能差がある」 と疑う。 ただし手ぶれの量は撮影ごとに違うので、 何枚も撮って平均的なブレを比較する必要がある。 これがサンプルサイズ $n_1, n_2$ と自由度の役割です。

3 群以上に話を広げると、 F 検定は ANOVA の心臓部に成長します。 「群間の平均がバラついている度合い」÷「群内の個体間ばらつき」 — これも結局は分散の比です。 SSDSE-B-2026 で 47 都道府県を 8 地方ブロックに分けて F 検定をかけると、 「地方間で差があるかどうか」 が分散の天秤で見えます。

🎨 概念図で押さえる — F検定の仕組み

F検定は「2つの分散の比」が偶然どこまで起こりうるかを問う。 比が1から大きく離れるほど分散が違うと判断する。

図 1: 等分散 vs 不等分散

等分散と不等分散等分散 (F≈1)分散ほぼ同じ → 受容不等分散 (F>>1)分散が違う → 棄却"/>

→ 山の幅が分散。 同じ幅なら F≈1、 違えば F が大きくなる。

図 2: F分布と棄却域

F分布と棄却域F_α棄却域 5%F = s1²/s2²F分布"/>

→ F値が臨界値 F_α を超えれば「分散が違う」と判定。

図 3: ANOVA における F検定

ANOVAのF検定群間分散 (大)÷群内分散 (小)= FF 大 → 群間差が顕著 → 平均は違う"/>

→ ANOVA は「群間分散 ÷ 群内分散」で平均差を検定する F検定の応用。

📐 F統計量

🍰 まずはやさしく

分散(データのばらつき)の比のことです。

3つ以上のグループに差があるか判定します。

地方ごとの食費の平均に差があるか調べます。

ここではF統計量の計算方法と定義を読みます。

$$ F = \frac{s_1^2}{s_2^2} \sim F(df_1, df_2) $$

2つの分散の比。 F分布は非対称で 0 から始まり右側に裾を引きます。

ANOVA での F統計量

$$ F = \frac{\text{群間平均平方}}{\text{群内平均平方}} = \frac{MS_{\text{between}}}{MS_{\text{within}}} $$

F が大きいほど「群間差が大きい」=「群差は本物」の証拠。

🎯 一元配置 ANOVA — 3群以上の平均差

H₀: μ₁ = μ₂ = μ₃ = ... = μ_k(全群同じ)
H₁: 少なくとも1つの群が異なる

例:「東日本・中部・西日本で食料費の平均に差があるか?」

分散の分解

$$ \text{全分散} = \text{群間分散} + \text{群内分散} $$

群間分散が群内分散より十分大きければ「差あり」と判定。

事後検定

ANOVA で「差がある」と分かっても「どこに差があるか」は別の検定が必要:

🔬 「F検定」を深く理解する

F分布の発見

Ronald A. Fisher(1925)が分散分析(ANOVA)で導入。 「F」は Fisher の F。 もとは George W. Snedecor が命名(1934)。

応用シナリオ

効果量 η²(イータ二乗)

$$ \eta^2 = \frac{SS_{\text{between}}}{SS_{\text{total}}} $$

ANOVA の説明力。 0.01 小、 0.06 中、 0.14 大。

📝 練習問題 — 理解度チェック

  1. この用語の基本定義を、 自分の言葉で説明できますか?
  2. この手法が使われる典型的なシナリオを3つ挙げられますか?
  3. この手法の前提条件・仮定を確認できますか?
  4. 結果を解釈する際の注意点は何ですか?
  5. 類似手法との違いを説明できますか?
  6. Python(または他言語)で実装できますか?
  7. SSDSE データで応用例を作成できますか?

F 検定の中心式は、 2 つの独立な標本分散の比です。 帰無仮説 $H_0: \sigma_1^2 = \sigma_2^2$ のもとで、 統計量は自由度 $(df_1, df_2) = (n_1-1, n_2-1)$ の F 分布に従います。

$$F = \frac{s_1^2}{s_2^2} \sim F(n_1-1,\ n_2-1)$$

🔬 数式を言葉で読み解く(核心)

この式が言うのは、 「2 つのグループのばらつき(分散)の比 が、 もし両方が同じ母分散から来ているなら、 1 のあたりに集まる」 という直感です。 比が 1 から大きく離れる(例: 3.5 とか 0.2)と、 「両グループの分散は同じ」 という仮定を疑う根拠になります。 たとえば SSDSE-B-2026 で東日本 vs 西日本の総人口の分散比が 2.3 なら、 「東日本の方が県間ばらつきが大きい」 と言えるかを F 分布の確率で判定します。

記号意味SSDSE 例
$s_1^2$第 1 群の不偏分散関東 1 都 6 県の総人口分散
$s_2^2$第 2 群の不偏分散関西 2 府 4 県の総人口分散
$df_1$分子の自由度$n_1 - 1 = 6$
$df_2$分母の自由度$n_2 - 1 = 5$
$F$分散比(検定統計量)2.3, 0.5 などの数値

🔬 ANOVA の F 統計量の数式を言葉で読み解く

ANOVA で使う F 統計量は分散の比ですが、 中身は「群間ばらつき」÷「群内ばらつき」 です。 これを式で書くと:

$$F = \frac{\text{MS}_{between}}{\text{MS}_{within}} = \frac{SS_B/(k-1)}{SS_W/(N-k)}$$

分子の $\text{MS}_{between}$ は「群の平均が全体の平均からどれくらい離れているか」、 分母の $\text{MS}_{within}$ は「同じ群の中での個体間ばらつき」 です。 もし群ごとの平均が同じなら(つまり地方別に人口平均は変わらないなら)分子は 0 に近づき F も 0 に近づきます。 逆に「関東は大きい、 東北は小さい」 という地方差があると分子が膨らみ F が大きくなる。 SSDSE-B-2026 で 8 地方ブロックの人口を ANOVA にかけると F は 10 を超えることが多く、 「地方間で人口に差がある」 と統計的に判定されます。

🧮 SSDSE で関東 vs 関西の分散比を実値計算

このコードでやること: SSDSE-B-2026 から関東 1 都 6 県と関西 2 府 4 県の総人口を抜き出し、 等分散性を F 検定で判定する。

📥 入力データ:

関東: 茨城, 栃木, 群馬, 埼玉, 千葉, 東京, 神奈川 (7 県) 関西: 三重, 滋賀, 京都, 大阪, 兵庫, 奈良, 和歌山 (7 県) 列: 総人口 (人)
 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
from scipy import stats

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]   # 2023年のみ(各県1行)

kanto_names  = ['茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県']
kansai_names = ['三重県','滋賀県','京都府','大阪府','兵庫県','奈良県','和歌山県']

kanto  = df[df['Prefecture'].isin(kanto_names)]['A1101'].astype(float)   # A1101=総人口
kansai = df[df['Prefecture'].isin(kansai_names)]['A1101'].astype(float)

s1_sq = kanto.var(ddof=1)
s2_sq = kansai.var(ddof=1)
F = s1_sq / s2_sq
df1, df2 = len(kanto)-1, len(kansai)-1
p = 2 * min(stats.f.cdf(F, df1, df2), 1 - stats.f.cdf(F, df1, df2))

print(f"関東分散 s1^2 = {s1_sq:,.0f}")
print(f"関西分散 s2^2 = {s2_sq:,.0f}")
print(f"F 統計量      = {F:.3f}")
print(f"自由度        = ({df1}, {df2})")
print(f"両側 p 値     = {p:.4f}")

📤 実行結果:

関東分散 s1^2 = 20,170,530,142,857 関西分散 s2^2 = 8,401,789,619,048 F 統計量 = 2.401 自由度 = (6, 6) 両側 p 値 = 0.3106

💬 結果の読み方: F = 2.40(関東の方が分散が大きい)ですが、 サンプルが各 7 県と少ないため p = 0.31 で 有意ではない。 「東京の存在で関東のばらつきは大きそう」 という直感は、 統計的には 5% 水準では確証されません。 サンプル数の制約が結論に効いていることが分かる典型例です。

🧭 F 検定 vs 代替手法 — 使い分けフローチャート

状況推奨手法Python 関数F 検定が不向きな理由
2 群、 正規性 OK、 等分散性確認F 検定(古典)scipy.stats.f.sf最も基本、 ここでは適用可
2 群、 正規性怪しいLevene 検定scipy.stats.leveneF 検定は正規性に過敏
2 群、 厳密に等分散性検定Bartlett 検定scipy.stats.bartlettF 検定より検出力高いが正規性要件強い
3 群以上、 等分散性Bartlett / Levenescipy.stats.bartlettF は 2 群限定
3 群以上、 平均の差one-way ANOVAscipy.stats.f_onewayANOVA の F は分散比ではなく平均差
回帰モデルの当てはまりregression F-teststatsmodels OLS.f_test複数係数の同時検定
不等分散・小標本Welch ANOVA / Brown-Forsythepingouin.welch_anova古典 F は等分散性が前提

🐍 Levene 検定で「正規性を疑った場合」の判定

このコードでやること: SSDSE-B-2026 の関東 vs 関西の人口に対し、 古典 F 検定と Levene 検定を併用し、 結論の安定性を確認する。

📥 入力データ: 関東 7 県 + 関西 7 県の総人口(前のセクションと同じ)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import pandas as pd
from scipy import stats

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]   # 2023年のみ(各県1行)
kanto  = df[df['Prefecture'].isin(['茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県'])]['A1101'].astype(float)
kansai = df[df['Prefecture'].isin(['三重県','滋賀県','京都府','大阪府','兵庫県','奈良県','和歌山県'])]['A1101'].astype(float)

# 古典 F 検定(自前実装)
F = kanto.var(ddof=1) / kansai.var(ddof=1)
p_F = 2 * min(stats.f.cdf(F, 6, 6), 1 - stats.f.cdf(F, 6, 6))

# Levene 検定(中央値ベース=Brown–Forsythe)
W, p_lev = stats.levene(kanto, kansai, center='median')

# Bartlett 検定
chi2, p_bar = stats.bartlett(kanto, kansai)

print(f"古典 F      : F={F:.3f}, p={p_F:.4f}")
print(f"Levene 検定 : W={W:.3f}, p={p_lev:.4f}")
print(f"Bartlett    : chi2={chi2:.3f}, p={p_bar:.4f}")

📤 実行結果:

古典 F : F=2.401, p=0.3106 Levene 検定 : W=1.307, p=0.2752 Bartlett : chi2=1.030, p=0.3102

💬 結果の読み方: 3 つの検定とも p > 0.05 で「等分散性は棄却できない」 と一致しました(古典 F=2.40, Levene, Bartlett いずれも p≒0.28〜0.31)。 検定によって p 値は少しずつ違いますが、 このデータでは結論は同じです。 「どの検定を使うかで結論が反転するケース」 では、 まず正規性を Shapiro-Wilk で確認し、 崩れていれば正規性に頑健な Levene(中央値ベース=Brown–Forsythe)を採用する手順が安全です。

🧮 SSDSE-B-2026 実値計算例 — F 検定を 47 都道府県データで実行

合成データではなく公的統計(SSDSE-B-2026, 2023 年)で F 検定の具体的な計算手順を、 実際に走るコードと実測出力で見せます。

① 等分散性の検定:「都市圏 vs 地方」で総人口の分散は等しいか?

2023 年の 47 都道府県を、 都市圏(東京・神奈川・大阪・愛知・埼玉・千葉・兵庫・福岡)8 都府県 と それ以外 39 道県に分けて、 総人口(列 A1101)の分散を比較します。 東京・大阪など巨大都市を含む都市圏は分散が桁違いに大きくなるはずです。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) 北海道 5,092,000 東京都 14,086,000 沖縄県 1,468,000 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import pandas as pd
from scipy import stats

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

# 都市圏 8 都府県 vs それ以外 39 道県、指標は A1101=総人口
metro = ['東京都','神奈川県','大阪府','愛知県','埼玉県','千葉県','兵庫県','福岡県']
m = df[df['Prefecture'].isin(metro)]['A1101'].astype(float)
r = df[~df['Prefecture'].isin(metro)]['A1101'].astype(float)

F = m.var(ddof=1) / r.var(ddof=1)          # 大きい方 / 小さい方
df1, df2 = len(m)-1, len(r)-1
crit = stats.f.ppf(0.95, df1, df2)         # 右側 5% 臨界値
p = 1 - stats.f.cdf(F, df1, df2)

print(f"都市圏 s1^2 = {m.var(ddof=1):,.0f}")
print(f"地方   s2^2 = {r.var(ddof=1):,.0f}")
print(f"F = {F:.2f}, df = ({df1}, {df2})")
print(f"F(0.05, {df1}, {df2}) = {crit:.2f}")
print(f"p 値 = {p:.2e}  ->  F >> 臨界値 なので等分散を強く棄却")

📤 実行結果:

都市圏 s1^2 = 8,311,746,000,000 地方 s2^2 = 799,415,236,167 F = 10.40, df = (7, 38) F(0.05, 7, 38) = 2.26 p 値 = 3.26e-07 -> F >> 臨界値 なので等分散を強く棄却

💬 結果の読み方: 都市圏の総人口分散は地方の約 10 倍(F=10.40)で、 臨界値 2.26 を大きく上回り p<0.001。 巨大都市を含む都市圏は「ばらつき自体が桁違い」 と統計的に確認できます。 この 2 群を平均比較する場合は等分散を仮定せず Welch 補正版の t 検定を使うべき、 という判断につながります。

② ANOVA:「4 地方ブロック(北・東・中・西)」で総人口の平均に差があるか?

2023 年の 47 都道府県を地理的に 4 ブロック(北日本 7・東日本 13・中日本 10・西日本 17)に分け、 総人口(列 A1101)の平均差を一元配置 ANOVA で検定します。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) 北海道 5,092,000 東京都 14,086,000 沖縄県 1,468,000 …(全 47 行)
 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
import pandas as pd, numpy as np
from scipy import stats

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

blocks = {
    '北日本': ['北海道','青森県','岩手県','宮城県','秋田県','山形県','福島県'],
    '東日本': ['茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県',
               '新潟県','富山県','石川県','福井県','山梨県','長野県'],
    '中日本': ['岐阜県','静岡県','愛知県','三重県','滋賀県','京都府','大阪府',
               '兵庫県','奈良県','和歌山県'],
    '西日本': ['鳥取県','島根県','岡山県','広島県','山口県','徳島県','香川県',
               '愛媛県','高知県','福岡県','佐賀県','長崎県','熊本県','大分県',
               '宮崎県','鹿児島県','沖縄県'],
}
groups = [df[df['Prefecture'].isin(v)]['A1101'].astype(float) for v in blocks.values()]

F, p = stats.f_oneway(*groups)          # 一元配置 ANOVA(A1101=総人口)
df1, df2 = len(groups)-1, sum(len(g) for g in groups)-len(groups)
crit = stats.f.ppf(0.95, df1, df2)

for name, g in zip(blocks, groups):
    print(f"{name}: n={len(g):>2}  平均={g.mean():,.0f}")
print(f"F = {F:.3f}, df = ({df1}, {df2}), p = {p:.4f}")
print(f"F(0.05, {df1}, {df2}) = {crit:.3f}  ->  F < 臨界値 なので有意でない")

📤 実行結果:

北日本: n= 7 平均=1,915,714 東日本: n=13 平均=3,947,154 中日本: n=10 平均=3,495,300 西日本: n=17 平均=1,451,588 F = 2.708, df = (3, 43), p = 0.0569 F(0.05, 3, 43) = 2.822 -> F < 臨界値 なので有意でない

💬 結果の読み方: 東日本・中日本の平均人口が北・西より大きく見えますが、 F=2.708 は臨界値 2.822 をわずかに下回り、 p=0.057 で 5% 水準では有意でない(東京を含む東日本内のばらつきが大きく、 群内分散が大きいため)。 「平均は違いそう」 という印象が有意性に届かない典型例です。 次の ③ で効果量を確認します。

③ 効果量 η² の計算

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) 北海道 5,092,000 東京都 14,086,000 沖縄県 1,468,000 …(全 47 行)
 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
import pandas as pd, numpy as np

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
blocks = {
    '北日本': ['北海道','青森県','岩手県','宮城県','秋田県','山形県','福島県'],
    '東日本': ['茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県',
               '新潟県','富山県','石川県','福井県','山梨県','長野県'],
    '中日本': ['岐阜県','静岡県','愛知県','三重県','滋賀県','京都府','大阪府',
               '兵庫県','奈良県','和歌山県'],
    '西日本': ['鳥取県','島根県','岡山県','広島県','山口県','徳島県','香川県',
               '愛媛県','高知県','福岡県','佐賀県','長崎県','熊本県','大分県',
               '宮崎県','鹿児島県','沖縄県'],
}
groups = [df[df['Prefecture'].isin(v)]['A1101'].astype(float) for v in blocks.values()]
y = np.concatenate([g.values for g in groups])
grand = y.mean()
ss_between = sum(len(g) * (g.mean() - grand)**2 for g in groups)
ss_within  = sum(((g - g.mean())**2).sum() for g in groups)
eta2 = ss_between / (ss_between + ss_within)

print(f"SS_between = {ss_between:.3e}")
print(f"SS_within  = {ss_within:.3e}")
print(f"eta^2 = SS_between / (SS_between + SS_within) = {eta2:.3f}")
print("Cohen の目安: 0.01=小, 0.06=中, 0.14=大  ->  効果量は『大』")

📤 実行結果:

SS_between = 5.721e+13 SS_within = 3.028e+14 eta^2 = SS_between / (SS_between + SS_within) = 0.159 Cohen の目安: 0.01=小, 0.06=中, 0.14=大 -> 効果量は『大』

💬 結果の読み方: η²=0.159 は Cohen の目安で「大」に相当し、 地方ブロックは総人口の全変動の約 16% を説明します。 効果量は大きいのに ② の ANOVA が有意でなかったのは、 群数 4・標本 47 と小さく検出力が不足しているため。 「効果量は大きいが有意でない」=サンプル設計の問題、 という読み方ができます(p 値と効果量は別物)。

🧮 数式に値を入れて手で計算する: 等分散性の F 検定

合成 2 標本で分散比 F 統計量を計算する。

Step 1: 各群の分散

n標本分散 s²
A1020
B85

Step 2: F 統計量

F = s_A² / s_B² = 20 / 5 = 4.0 df1 = n_A - 1 = 9, df2 = n_B - 1 = 7 F(0.05, 9, 7) ≈ 3.68 4.0 > 3.68 → 等分散性 棄却

🐍 Python で再現

1
2
3
4
5
6
7
8
from scipy import stats
F = 20 / 5
df1, df2 = 9, 7
crit = stats.f.ppf(0.95, df1, df2)
p = 1 - stats.f.cdf(F, df1, df2)
print(f"F = {F}")
print(f"臨界値: {crit:.3f}")
print(f"p = {p:.4f}")

📤 実行結果

F = 4.0 臨界値: 3.677 p = 0.0388

💬 手計算 (Step 2) F=4.0 と Python 出力が完全一致。 p<0.05 で分散異なる。

🐍 Python での F検定

🎯 このコードでやること:SSDSE-B-2026 を data/raw/SSDSE-B-2026.csv から読み込み、 2023 年の地域 3 ブロック (北海道・東北、 関東、 関西) の 総人口 (列 A1101) について (1) 分散比 F 検定 (関東 vs 北海道・東北)(2) 3 群一元配置 ANOVA を実施し、 Tukey HSD で群間差を確認する。

📥 入力データ (SSDSE-B-2026, 2023 年の関連列、 5 行抜粋):

Code Prefecture A1101(総人口) ブロック R01000 北海道 5092000 北海道・東北 R02000 青森県 1184000 北海道・東北 R13000 東京都 14086000 関東 R14000 神奈川県 9229000 関東 R27000 大阪府 8763000 関西
 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
import pandas as pd
import numpy as np
from scipy import stats

# SSDSE-B-2026 を読み込み、2023 年の 3 地域に分割(指標 A1101=総人口)
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
tohoku = df[df['Prefecture'].isin(['北海道','青森県','岩手県','宮城県','秋田県','山形県','福島県'])]['A1101'].astype(float)
kanto  = df[df['Prefecture'].isin(['茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県'])]['A1101'].astype(float)
kansai = df[df['Prefecture'].isin(['三重県','滋賀県','京都府','大阪府','兵庫県','奈良県','和歌山県'])]['A1101'].astype(float)

# (1) 分散比 F 検定: 関東 vs 北海道・東北(関東の方が分散が大きいと予想)
s1, s2 = kanto.var(ddof=1), tohoku.var(ddof=1)
F = s1 / s2
df1, df2 = len(kanto)-1, len(tohoku)-1
p_var = 2 * min(stats.f.cdf(F, df1, df2), 1-stats.f.cdf(F, df1, df2))
print(f'[F 検定] 関東/東北 分散比 F = {F:.3f}, df=({df1},{df2}), p={p_var:.4f}')

# (2) 3 群一元配置 ANOVA
F_anova, p_anova = stats.f_oneway(tohoku, kanto, kansai)
print(f'[ANOVA] F = {F_anova:.3f}, p = {p_anova:.4f}')

# (3) Tukey HSD 事後検定で群間差を特定
from statsmodels.stats.multicomp import pairwise_tukeyhsd
y     = np.concatenate([tohoku, kanto, kansai])
group = ['東北']*len(tohoku) + ['関東']*len(kanto) + ['関西']*len(kansai)
print(pairwise_tukeyhsd(y, group, alpha=0.05))

📤 実行結果:

[F 検定] 関東/東北 分散比 F = 9.218, df=(6,6), p=0.0161 [ANOVA] F = 3.354, p = 0.0578 Multiple Comparison of Means - Tukey HSD, FWER=0.05 ==================================================================== group1 group2 meandiff p-adj lower upper reject -------------------------------------------------------------------- 東北 関東 4302428.5714 0.054 -65853.2581 8670710.401 False 東北 関西 1225714.2857 0.7572 -3142567.5438 5593996.1153 False 関東 関西 -3076714.2857 0.1986 -7444996.1153 1291567.5438 False --------------------------------------------------------------------

💬 結果の読み方:(1) 関東/東北の総人口分散比 F=9.22, p=0.016 → 関東の人口分散の方が有意に大きい (東京都が外れ値的に大きいため)。 (2) 3 群 ANOVA では F=3.35, p=0.058 で 5% 水準では有意に届かず、 平均差は「あるとは言い切れない」。 (3) Tukey HSD でも全ペアが reject=False(東北 vs 関東でさえ p=0.054 と僅差で非有意)→ 関東の人口水準は高そうだが、 関東内のばらつき(群内分散)が大きく、 群数 3・各 7 県の小標本では統計的な確証には届かない。 (1) の等分散が棄却された時点で、 本来は Welch の ANOVA に切り替えるのが安全という教訓も得られる。

🚧 落とし穴と注意点

🐍 Python 実装のバリエーション — scipy / statsmodels / pingouin

① scipy.stats.f_oneway による一元配置 ANOVA

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) 北海道 5,092,000 東京都 14,086,000 沖縄県 1,468,000 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import pandas as pd
from scipy import stats

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023].copy()
# 47 都道府県を 4 地方ブロックに区分(region 列を作る)
north = ['北海道','青森県','岩手県','宮城県','秋田県','山形県','福島県']
east  = ['茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県',
         '新潟県','富山県','石川県','福井県','山梨県','長野県']
center= ['岐阜県','静岡県','愛知県','三重県','滋賀県','京都府','大阪府',
         '兵庫県','奈良県','和歌山県']
df['region'] = df['Prefecture'].map(
    lambda x: '北' if x in north else '東' if x in east else '中' if x in center else '西')

# A1101=総人口 を地方ブロックで比較する一元配置 ANOVA
groups = [g['A1101'].astype(float).values for _, g in df.groupby('region')]
F, p = stats.f_oneway(*groups)
print(f'F = {F:.3f}, p = {p:.4f}')
📤 実行例(実測) F = 2.708, p = 0.0569

② scipy.stats.f による分散比検定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import numpy as np
from scipy import stats

# region 列は①で作成済み。「東」ブロック vs 「北」ブロックの総人口分散比
x1 = df[df['region'] == '東']['A1101'].astype(float).values
x2 = df[df['region'] == '北']['A1101'].astype(float).values

var1 = np.var(x1, ddof=1)
var2 = np.var(x2, ddof=1)
F = var1 / var2 if var1 > var2 else var2 / var1        # 大きい方 / 小さい方
df1 = (len(x1) if var1 > var2 else len(x2)) - 1
df2 = (len(x2) if var1 > var2 else len(x1)) - 1

p = 2 * (1 - stats.f.cdf(F, df1, df2))                 # 両側
print(f'F = {F:.3f}, df = ({df1}, {df2}), p = {p:.4f}')
📤 実行例(実測) F = 7.659, df = (12, 6), p = 0.0204

③ statsmodels の anova_lm で本格的 ANOVA

 1
 2
 3
 4
 5
 6
 7
import statsmodels.api as sm
from statsmodels.formula.api import ols

# A1101=総人口 を region で説明する ANOVA テーブル
model = ols('A1101 ~ C(region)', data=df).fit()
anova_table = sm.stats.anova_lm(model, typ=2)
print(anova_table)
📤 実行例(実測) sum_sq df F PR(>F) C(region) 5.720787e+13 3.0 2.707976 0.056902 Residual 3.028016e+14 43.0 NaN NaN

④ pingouin で効果量とともに ANOVA

 1
 2
 3
 4
 5
import pingouin as pg

result = pg.anova(data=df, dv='A1101', between='region', detailed=True)
print(result)
# 出力:F値、 p値、 partial η² まで自動計算
📤 実行例(実測) Source SS DF MS F p_unc np2 0 region 5.720787e+13 3 1.906929e+13 2.707976 0.056902 0.158907 1 Within 3.028016e+14 43 7.041899e+12 NaN NaN NaN

⑤ Welch の ANOVA(等分散を仮定しない)

 1
 2
 3
 4
import pingouin as pg

result_welch = pg.welch_anova(data=df, dv='A1101', between='region')
print(result_welch)
📤 実行例(実測) Source ddof1 ddof2 F p_unc np2 0 region 3 16.947586 2.795459 0.071809 0.158907

⑥ 多重比較(Tukey HSD)

 1
 2
 3
 4
from statsmodels.stats.multicomp import pairwise_tukeyhsd

tukey = pairwise_tukeyhsd(endog=df['A1101'], groups=df['region'], alpha=0.05)
print(tukey.summary())
📤 実行例(実測) Multiple Comparison of Means - Tukey HSD, FWER=0.05 ==================================================================== group1 group2 meandiff p-adj lower upper reject -------------------------------------------------------------------- 中 北 -1579585.7143 0.6253 -5074410.4564 1915239.0279 False 中 東 451853.8462 0.9773 -2531070.2533 3434777.9457 False 中 西 -2043711.7647 0.2299 -4869940.9862 782517.4567 False 北 東 2031439.5604 0.3714 -1293197.6604 5356076.7813 False 北 西 -464126.0504 0.9797 -3648925.5855 2720673.4847 False 東 西 -2495565.6109 0.0659 -5108415.4504 117284.2287 False ---------- …(以下略)

⑦ Levene 検定(F 検定の頑健な代替)

 1
 2
 3
 4
 5
 6
from scipy import stats

groups = [g['A1101'].astype(float).values for _, g in df.groupby('region')]
stat, p = stats.levene(*groups, center='median')
print(f'Levene W = {stat:.3f}, p = {p:.4f}')
# center='median' は Brown–Forsythe 法。 正規性に頑健。
📤 実行例(実測) Levene W = 2.265, p = 0.0945

⚠️ F 検定の落とし穴 — 実務で必ず引っかかるポイント 7 選

① F 検定は正規性に「敏感」である

t 検定は中心極限定理で正規性の崩れに比較的頑健ですが、 F 検定(特に等分散性検定)は正規性の崩れに敏感です。 裾が重い・歪んだ分布では F 検定の Type I エラー率が大きく狂います。 47 都道府県の人口や所得のような分布では、 等分散性検定として F 検定よりも Levene 検定や Brown–Forsythe 検定を使う方が頑健です。 正規性は QQ プロットや Shapiro–Wilk で必ず確認しましょう。

② ANOVA が有意でも「どの群間に差があるか」は分からない

ANOVA の F 検定は「少なくとも 1 つの群が他と違う」を示すだけで、 どのペアが違うかは別途多重比較が必要です。 単純に各ペアで t 検定を 3 回(3 群なら)行うと、 全体の Type I エラーが 5% を超え(約 14%)、 偽陽性が増えます。 Tukey HSD や Bonferroni、 Holm 法など、 群数に応じた補正を必ず適用してください。

③ サンプルサイズが大きいと「実質的に同じ分散」でも有意になる

F 検定はサンプル数が大きくなるほど検出力が上がるため、 実質的に無視できる差でも統計的に有意と判定されます。 例えば s₁² = 100、 s₂² = 105 でも N = 1000 ずつあれば有意になりますが、 実務的にこの差は無意味です。 必ず効果量(η², 分散比そのもの)と組み合わせて報告し、 統計的有意性と実質的有意性を区別しましょう。

④ 「等分散性の前検定 → t 検定」という二段階手続きは推奨されない

かつては「F 検定で等分散を確認してから Student の t 検定、 等分散でなければ Welch の t 検定」という流れが推奨されました。 しかし現代の統計学では、 初めから Welch の t 検定(または Welch の ANOVA)を使う方が安全とされています。 二段階手続きは Type I エラーが累積し、 等分散性の検定自体の検出力も問題になります。

⑤ F 分布は右に裾を引く非対称分布である

正規分布や t 分布と違い、 F 分布は左右対称ではなく、 値は常に正です。 分散比を計算するときは慣例的に「大きい分散 / 小さい分散」として F ≥ 1 とし、 右側のみを棄却域として α/2 で見ます(両側検定の場合)。 単純に「F = s₁²/s₂² が 0.5 だから棄却しない」と判断してはいけません。

⑥ 反復測定データに通常の ANOVA を適用してしまう

同一被験者を複数時点で測定したデータに通常の one-way ANOVA を適用すると、 観測の独立性が壊れ F 統計量が過大 / 過小評価されます。 反復測定 ANOVA、 混合効果モデル(lme4 / statsmodels.MixedLM)、 GEE などの相関構造を扱える手法を使う必要があります。 球面性の仮定(Mauchly 検定)にも注意。

⑦ 群サイズが不均衡だと不安定になる

「都市圏 8 県 vs 地方 39 県」のように群サイズが極端に偏ると、 F 検定は分散の同等性を強く要求するようになり、 仮定の崩れに敏感になります。 また Type III 平方和(不均衡 ANOVA で必要)の選択も問題になります。 サンプルサイズが揃わない場合は、 Welch の ANOVA、 混合モデル、 もしくはノンパラメトリック(Kruskal–Wallis)を検討してください。

🎨 直感をさらに掘る — F は「分散比」ひとつで三役をこなす

F 検定を一言でいえば 「2 つの分散を割り算し、 その比 F が 1 からどれだけ離れているかを問う」 検定です。 F 分布は 0 から始まり右へ長い裾を引く非対称分布で、 帰無仮説(2 つの分散は同じ母分散から来る)が正しければ比は 1 の周辺に集まります。 比が 1 から大きく離れるほど、 F 分布の右の裾に飛び出して p 値が小さくなり「分散が違う/群差がある」と判定されます。 大事なのは、 まったく同じ「分散比」という発想が、 使う場面によって三つの顔を持つことです。

分子(大きくしたい方)分母(誤差)自由度問い
分散の等質性検定$s_1^2$$s_2^2$$(n_1-1,\ n_2-1)$2 群のばらつきは等しいか
ANOVA群間平均平方 $MS_B$群内平均平方 $MS_W$$(k-1,\ N-k)$$k$ 群の平均は等しいか
回帰の全体検定回帰平均平方 $MSR$残差平均平方 $MSE$$(p,\ n-p-1)$全係数 = 0 を棄却できるか

この統一像があると「なぜ回帰の当てはまりも分散分析も同じ F で測れるのか」がすっきりします。 いずれも 「説明された変動 ÷ 説明できない変動」 を自由度で調整した比だからです。

🔗 2 群なら F = t² — 実測で確認

群が 2 つだけのとき、 ANOVA の F 統計量は t 検定の統計量の 2 乗にぴったり一致します($F(1,\nu) = t_\nu^2$)。 「平均差の t 検定」と「分散比としての F 検定」は、 2 群では同じ検定の別表現なのです。 SSDSE-B-2026(cp932, skiprows=[1], 2023 年 47 都道府県の実測)で 東日本 23 県 vs 西日本 24 県の食料費 L322101(二人以上世帯の平均、 円)を比べると、 $t = 2.7722$ に対し $t^2 = 7.6849$、 一元配置 ANOVA の $F = 7.6849$ と一致します。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 L322101(食料費(二人以上の世帯)) 北海道 74,341 東京都 97,776 沖縄県 73,453 …(全 47 行)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import pandas as pd
from scipy import stats
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023].copy()
df['pref_no'] = df['Code'].str[1:3].astype(int)   # 都道府県番号 01..47
# 東日本(1..23) vs 西日本(24..47) の食料費 L322101(円)
e = df[df['pref_no'] <= 23]['L322101'].astype(float)
w = df[df['pref_no'] >= 24]['L322101'].astype(float)
# (1) 分散比検定(両側): H0 は 2 群の分散が等しい
F = e.var(ddof=1) / w.var(ddof=1)
d1, d2 = len(e) - 1, len(w) - 1
p = 2 * min(stats.f.cdf(F, d1, d2), stats.f.sf(F, d1, d2))
print(f'分散比 F = {F:.3f}  df = ({d1}, {d2})  両側 p = {p:.4f}')
# (2) F = t^2 の確認(2 群の平均差)
t, _ = stats.ttest_ind(e, w, equal_var=True)
Fa, _ = stats.f_oneway(e, w)
print(f't = {t:.4f}   t^2 = {t*t:.4f}   ANOVA F = {Fa:.4f}')

📤 実行結果:

分散比 F = 1.751 df = (22, 23) 両側 p = 0.1898 t = 2.7722 t^2 = 7.6849 ANOVA F = 7.6849

💬 読み方: 食料費の ばらつき は東西で有意差なし(分散比 F = 1.75, p = 0.19)。 一方 平均 は東(約 82,853 円)が西(約 78,437 円)より高く、 t 検定で有意(p ≈ 0.008)。 そしてその F は t の 2 乗に一致します。 このように「分散を比べる F」と「平均差の t」は別の問いですが、 2 群の平均差検定に限っては F と t² が同一物である、 という関係を実データで確認できます。

⚠️ さらなる落とし穴 — F 検定で足をすくわれる追補 7 点

⑧ 正規性への過敏さは「等分散検定」で特に致命的

2 群の分散比 F 検定は、 正規性の崩れに極めて敏感です。 裾が重い・歪んだ分布では、 分散が本当は等しくても F 検定が「差あり」と誤判定しやすくなります(第一種の過誤の膨張)。 47 都道府県の人口・所得・地価のように東京や大阪が突出する分布では特に危険。 等分散性を調べたいなら、 分散比 F ではなく Levene 検定(中央値まわりの絶対偏差を使う Brown–Forsythe 版が頑健)や Bartlett 検定を第一選択にしてください(scipy.stats.levene / scipy.stats.bartlett)。 Bartlett は検出力が高い代わりに正規性要件が強く、 Levene は正規性の崩れに頑健、 という使い分けです。

⑨ 片側か両側か — 分散比検定は方向で p 値が変わる

ANOVA や回帰の全体 F は本質的に 片側(右側)検定です(分子が大きいときだけ棄却)。 一方、 2 群の分散比検定で「どちらが大きいか未定」なら 両側にすべきで、 上のコードのように $2\times\min(\text{cdf},\ \text{sf})$ で p 値を出します。 慣例で「大きい分散 / 小さい分散」として F ≥ 1 に固定し、 右側確率を 2 倍する流儀もあります。 scipy.stats.f.sf(F, d1, d2) をそのまま片側 p として使うと、 分散比検定では p を半分に見積もってしまうので注意。

⑩ 回帰の「全体 F」と「個別 t」を混同しない

重回帰では、 全体 F 検定が有意でも 個々の係数が有意とは限らず、 逆に全体 F は有意なのにどの t も有意でない、 という現象も起こります(多重共線性の典型症状)。 全体 F は「モデル全体が偶然以上か」、 個別 t は「他の変数を固定したときその 1 変数が効くか」を問う別物です。 「$R^2$ が高い」ことと「全体 F が有意」も別概念で、 標本が小さいと $R^2$ が高くても全体 F が有意にならないことがあります。

⑪ 自由度の取り違えが結論をひっくり返す

F 分布は $(df_1, df_2)$ の 2 つの自由度で形が決まり、 順番を入れ替えると臨界値が変わります。 ANOVA は $(k-1,\ N-k)$、 回帰の全体検定は $(p,\ n-p-1)$($p$ は定数項を除く説明変数の数)、 偏 F 検定は $(q,\ n-k)$($q$ は追加した係数の数)。 分子・分母を取り違えると p 値が大きく狂います。 同じ観測 F でも自由度が違えば有意にも非有意にもなり得ます。

⑫ ANOVA が有意 = 「どこかで差」だけ、 その先は多重比較

これは既出の落とし穴②の再確認ですが重要です。 ANOVA の F が有意でも「どのペアが違うか」は言えません。 有意になった後の総当たり t 検定は 多重比較問題(多重検定)を引き起こし、 全体の第一種過誤が膨らみます。 Tukey HSD、 Bonferroni、 Holm、 あるいは偽発見率(FDR)制御を必ず併用してください。

⑬ 外れ値 1 点で分散比が跳ねる

F 検定の分子・分母はどちらも 分散(偏差の 2 乗和)なので、 外れ値の影響を強く受けます。 たった 1 つの極端値で分散比が数倍になり、 有意/非有意が反転することも。 検定前に箱ひげ図や散布図で外れ値を確認し、 必要なら頑健統計(中央値ベースの Brown–Forsythe など)へ切り替えましょう。 除外する場合はドメイン的根拠を明示すること。

⑭ 有意性だけ報告し「効果量」を落とす

F 値と p 値だけでは「差の大きさ」が伝わりません。 サンプルが大きいと実質的に無視できる差でも有意になります(既出③)。 ANOVA なら $\eta^2$・$\omega^2$、 回帰なら $R^2$・調整 $R^2$、 2 群なら分散比そのものを必ず併記し、 統計的有意性と実質的有意性を切り分けてください。

🚀 発展 — 分散比検定・ANOVA・回帰の全体/部分 F 検定を体系で

① 分散比検定(2 群の等分散性)

最も素朴な F 検定。 帰無仮説 $H_0:\sigma_1^2=\sigma_2^2$ のもと $F=s_1^2/s_2^2 \sim F(n_1-1,\ n_2-1)$。 上の実測(食料費 東西)では $F=1.751$, $df=(22,23)$, 両側 $p=0.19$ で等分散を棄却できませんでした。 ただし前述のとおり、 実務では正規性に頑健な Levene 検定(中央値版 = Brown–Forsythe)や、 検出力の高い Bartlett 検定を代替に使うのが定石です。 これらは 3 群以上の等分散性も一度に検定できます。

② ANOVA の F — 分散の分解

全変動を「群間」と「群内」に分解します。$SS_T = SS_B + SS_W$、 それぞれを自由度で割って平均平方にし、

$$F = \frac{MS_B}{MS_W} = \frac{SS_B/(k-1)}{SS_W/(N-k)} \sim F(k-1,\ N-k)$$

群間の平均が離れているほど $SS_B$ が膨らみ F が大きくなります。 scipy.stats.f_onewaystatsmodelsanova_lm で計算できます。

③ 回帰の全体 F 検定と部分(偏)F 検定 — 実測

全体 F 検定は「すべての回帰係数 = 0」を一度に検定します:

$$F = \frac{SSR/p}{SSE/(n-p-1)} = \frac{R^2/p}{(1-R^2)/(n-p-1)}$$

部分 F 検定(入れ子モデル比較)は、 縮小モデルに変数群($q$ 個)を足したとき、 残差平方和の減り $SSE_{reduced}-SSE_{full}$ が偶然以上かを問います:

$$F = \frac{(SSE_{r}-SSE_{f})/q}{SSE_{f}/(n-k)} \sim F(q,\ n-k)$$

SSDSE-B-2026(2023 年 47 県の実測)で、 大学学生数 E6302 を予測します。 縮小モデルは「総人口 A1101 のみ」、 完全モデルは「+ 大学数 E6102」。 大学数を足すと $R^2$ が 0.789 → 0.964 に上がり、 その改善が有意か(部分 F)を anova_lm で検定します。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) E6102(大学数) E6302(大学学生数) 北海道 5,092,000 37 79,983 東京都 14,086,000 144 681,667 沖縄県 1,468,000 8 17,937 …(全 47 行)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import pandas as pd
import statsmodels.api as sm
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
y  = df['E6302'].astype(float)        # 大学学生数(被説明変数)
x1 = df['A1101'].astype(float)        # 総人口
x2 = df['E6102'].astype(float)        # 大学数
# 縮小モデル:大学学生数 ~ 総人口
m_r = sm.OLS(y, sm.add_constant(pd.DataFrame({'x1': x1}))).fit()
# 完全モデル:+ 大学数
m_f = sm.OLS(y, sm.add_constant(pd.DataFrame({'x1': x1, 'x2': x2}))).fit()
print(f'縮小 R2={m_r.rsquared:.3f}  全体F={m_r.fvalue:.1f}  p={m_r.f_pvalue:.1e}')
print(f'完全 R2={m_f.rsquared:.3f}  全体F={m_f.fvalue:.1f}  p={m_f.f_pvalue:.1e}')
print(sm.stats.anova_lm(m_r, m_f))   # 入れ子モデル比較 = 部分F検定

📤 実行結果(要点):

縮小 R2=0.789 全体F=168.8 p=7.9e-17 完全 R2=0.964 全体F=587.4 p=1.8e-32 部分 F(1, 44) = 212.55, p ≈ 1.9e-18 → 大学数の追加は有意

💬 読み方: 総人口だけでも全体 F は極めて有意(モデルは偶然でない)。 そこに大学数を足すと部分 F = 212.55 が示すとおり当てはまりが有意に向上し、 大学数はモデルに残す価値があると判断できます。 部分 F は「変数選択」の統計的な根拠になります。

④ F 分布と t 分布・χ² 分布の関係

F 分布は独立な 2 つの χ² 変数の比(各々を自由度で割ったもの)として定義されます:

$$F = \frac{\chi^2_{d_1}/d_1}{\chi^2_{d_2}/d_2} \sim F(d_1,\ d_2)$$

ここから兄弟関係が見えます。(a) 分子の自由度が 1 なら $F(1,\nu)=t_\nu^2$(t の 2 乗)。 (b) 分母の自由度を無限大にすると $d_1 F \to \chi^2_{d_1}$(χ² に収束)。 つまり t・χ²・F は同じ正規理論から派生した一族で、 分布としても検定としても地続きです。

⑤ 効果量 — F の「大きさ」を標準化する

p 値は標本サイズに依存するため、 効果の大きさは別途報告します。 ANOVA では:

効果量の詳細は 効果量 のページを参照。 回帰では $R^2$・調整 $R^2$ が対応する効果量です。

🔗 関連ページ

※ Levene 検定・Bartlett 検定・Welch の ANOVA は本教材に独立ページがないため、 リンクではなく scipy.stats.levene / scipy.stats.bartlett / pingouin.welch_anova として実装名で示しています。

🗺️ 概念マップ — 3つの視点で体系を理解する

F検定 がデータサイエンスの体系の中でどこに位置するかを、 3つの異なる視点で可視化します。 同じ情報でも見方を変えると気付きが変わります。

📍 体系階層のパス

🌐 統計・データサイエンス推測統計検定F検定

① 🔗 関係マップ — 「他の手法とどう繋がっているか」

中心に F検定 を置き、 そこから t検定・χ²検定・分散・p値・重回帰・ノンパラ検定 など 計 14 個の用語へ、 前提・兄弟・発展形といった関係を矢印で結んでいます。 線がどちら向きかを見れば、 先に読むべき用語あとから読む用語が分かります。 ノードはドラッグで動かせ、 ホイールでズーム、 クリックでその用語のページへ遷移します。

凡例:現在の用語上位カテゴリ兄弟(並列)前提発展形応用先2階層先

② ⭕ 包含マップ — 「どのカテゴリに含まれているか」

大きな円が小さな円を包含する Circle Packing 図。 「F検定」は緑色でハイライト

📍現在地:統計・データサイエンス

③ 🌳 ツリーマップ — 「面積で見るボリューム比較」

長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「F検定」は緑色でハイライト

🎯 3つのマップの使い分け

マップ 分かること こんな時に見る
🔗 関係マップ手法間の横の関係(前提→発展→応用)「次に何を学べばよい?」 学習順序の判断
⭕ 包含マップ分類体系の入れ子構造(上位⊃下位)「この手法はどんなジャンルに属する?」
🌳 ツリーマップ分野の規模比較(面積=ボリューム)「データサイエンス全体の俯瞰像」

💡 3 つの図は同じ位置関係を別の角度から描いています。 関係マップは F検定隣に何が並ぶかを、 包含マップとツリーマップは 統計・データサイエンス検定 → F検定 という入れ子の位置を示します。 「検定には他に何があったか」を思い出したいときは包含マップを、 「次に何を読むか」を決めたいときは関係マップを開いてください。

🔗 隣接手法への橋渡し

「F検定」は単独で完結せず、 隣接する手法と接続することで分析パイプラインの一部として機能する。 以下に具体的な接続関係を示す。

F 検定は分散比 F = s₁²/s₂² が F(df₁, df₂) 分布に従うことを利用するため、 (1) 各群が正規分布 (2) 観測の独立性 という 2 仮定が成立しないと p 値が歪む。 ANOVA でグループ間平均差を検定する前に Levene 検定 (1960) で分散均一性確認 + Shapiro-Wilk で正規性確認、 違反時は Welch's ANOVA か Kruskal-Wallis に切り替える。

🌳 手法選択フロー

「f test」を含む手法選択は、 データの性質・分析目的・運用制約の 3 軸で決まる。 以下に典型シナリオと対応する手法の組合せを示す。

典型シナリオ別の手法選択

シナリオ重視する観点候補手法
2 群間の分散比較等分散性検定 (Welch t 検定の前段)F 検定 (Fisher 1925) / Levene 検定
3 群以上の平均差検定群間 / 群内分散の比 F = MS_b/MS_w一元配置 ANOVA / 事後検定 Tukey HSD
回帰モデル全体の有意性全係数=0 の帰無仮説 (overall F)重回帰の F 統計量
入れ子モデルの比較削減モデル vs 完全モデル偏 F 検定 / 尤度比検定
正規性が疑わしいノンパラメトリック代替Kruskal-Wallis 検定 / 順列検定
等分散性が破れているWelch 補正 / ロバスト分散推定Welch ANOVA (Welch 1951) / Brown-Forsythe 検定

選んだ後の検証ステップ

  1. 前処理確認: 標準化 / 欠損処理 / カテゴリ変数のエンコード が適切か
  2. ハイパラ調整: 交差検証で安定する値を選ぶ
  3. 性能評価: タスクに応じた指標 (RMSE / Accuracy / F1 / AUC / シルエット等) を複数併用
  4. 頑健性チェック: 別手法 / 別シードで結果が大きく違わないか確認
  5. 解釈: 結果を分野知識と照らし合わせ、 意味のある発見になっているか検討

🎮 触って理解する

下のスライダー(またはグラフを直接ドラッグ)で、 3 つの群の 平均の広がり Δ(群間分散)・群内のばらつき σ(群内分散)・各群の標本サイズ n を動かしてみよう。 上のパネルは 3 群のデータ点と群平均・総平均、 下のパネルは自由度 $(df_1, df_2)$ の F 分布・棄却域(赤・α=0.05)・観測された $F$・p 値をリアルタイムに描く。 群間のばらつきが群内より大きくなるほど $F$ が右へ動き、 p 値が小さくなる 様子を体感できる。 F 分布の pdf / cdf は正則化不完全ベータ関数で正確に計算している。

💡 上のグラフを指またはマウスでドラッグ: 左右で Δ(群の離れ具合)、 上下で σ(点の散らばり)が変わります。


👁️ 直感 — 分子と分母の綱引き

F 検定の心臓は割り算ひとつ。 分子に「群と群ので平均がどれだけ離れているか」(群間分散)、 分母に「同じ群ので個体がどれだけ散らばっているか」(群内分散)を置く。 スライダーで Δ を大きくすると群の位置が縦に離れて分子が膨らみ、 σ を小さくすると点が締まって分母が縮む。 どちらも $F$ を押し上げ、 F 分布の右の裾に統計量が飛び出して p 値が小さくなる。 逆に Δ≈0 なら群の違いは誤差に埋もれ、 $F$ は 1 付近に落ち着く。 標本サイズ n を増やすと同じ Δ でも分子の自由度あたりの寄与が安定し、 わずかな差でも検出しやすくなる(検出力の上昇)。

⚠️ よくある落とし穴 — 前提が崩れると p 値は嘘をつく

このデモの p 値が正しいのは、 各群が正規分布し、 群間で分散が等しい(等分散) という前提が成り立つときだけ。 外れ値や歪んだ分布があると $F$ は前提を裏切り、 p 値は信用できなくなる。 特に群ごとに標本数が大きく違い、 かつ分散も違う場合、 通常の ANOVA は第一種の過誤(本当は差がないのに「差あり」と誤判定)を膨らませる。 実務では正規性を Shapiro–Wilk 検定、 等分散性を Levene / Bartlett 検定で事前確認し、 崩れていれば Welch の ANOVA や Kruskal–Wallis 検定 に切り替える。 また F 検定が有意でも「どの群が違うか」は分からない — 多重比較(Tukey HSD / Bonferroni)が別途必要。

🚀 発展 — 同じ「分散比」が二役をこなす

同じ分散比の発想は、 二つの主役に化ける。 (1) 一元配置 ANOVA — 上のデモそのもので、 $F = MS_{between}/MS_{within}$、 $df=(k-1,\ N-k)$。 (2) 回帰の全体検定 — 重回帰で「すべての係数が 0」という帰無仮説を、 説明された分散 ÷ 残差分散の比 $F=\dfrac{SSR/p}{SSE/(n-p-1)}$ で一気に検定する。 $R^2$ が高くても、 この全体 F が有意でなければモデルは偶然の当てはまりかもしれない。 ネストしたモデルの比較(偏 F 検定)も同じ枠組みで、 「追加した変数群が分散を有意に説明したか」 を問う。 このように F 検定は「複数のパラメータをまとめて一つの数値で検定する」 統一言語なのだ。