論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説(ジャストインタイム型データサイエンス教育)
分散分析(ANOVA)
Analysis of Variance
3群以上の平均比較 — t検定の自然な拡張
仮説検定群間比較F分布実験計画法

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

本ページでは、 分散分析 (ANOVA)を統合的に解説します。 一元配置二元配置反復測定post-hoc 検定効果量を一気通貫で扱います。

ANOVA は「3 群以上の平均が等しいか」を検定する手法。 名前は「分散」ですが、 検定対象は平均値です。 群内変動と群間変動を比較することから「分散」と呼ばれます。

🔖 🔖 キーワード索引(チップから該当箇所へジャンプ)

論文記事から各用語のリンクをクリックすると、 該当箇所が開きます:

なぜANOVA F分布 一元配置ANOVA 二元配置ANOVA 交互作用 反復測定ANOVA 平方和分解 群間平方和 群内平方和 前提条件 Post-hoc検定 Tukey HSD Bonferroni 効果量 (η²) ノンパラ代替

💡 30秒で分かる結論

🎨 直感で掴む — ANOVAの本質

ANOVA(分散分析)の核心は名前のとおり 「分散の分解」。 SSDSE-B-2026 で 47 都道府県を 北日本・東日本・西日本 の 3 ブロックに分けて出生率を比較するとき、 「全体のバラつき」を 群間のバラつき(地域差)群内のバラつき(地域内の差) に切り分け、 その比率(F値)で「地域差は本物か」を検定します。

比喩で言うと、 ある楽団の演奏のばらつきを「楽器セクション間のばらつき」と「同じセクション内のばらつき」に切り分けて、 もしセクション間のバラつきが圧倒的に大きければ「セクションごとに本当に差がある」と判断するイメージ。 ANOVAは t検定の自然な拡張で、 群が 3 つ以上のときに 多重比較の罠 を避けながら一発で検定できる点が魅力です。

🔬 数式を言葉で読み解く — 分散分解と F値

$$ \text{SS}_{\text{total}} = \text{SS}_{\text{between}} + \text{SS}_{\text{within}}, \quad F = \frac{\text{SS}_{\text{between}}/(k-1)}{\text{SS}_{\text{within}}/(N-k)} = \frac{\text{MS}_{\text{between}}}{\text{MS}_{\text{within}}} $$
記号意味SSDSE-B-2026 例
$k$群数3 地域ブロック
$N$総サンプル数47 都道府県
$\text{SS}_{\text{between}}$群間平方和(地域差)地域ブロックの平均出生率のバラつき
$\text{SS}_{\text{within}}$群内平方和(誤差)同じブロック内の県間バラつき
$F$「シグナル/ノイズ」比1 を大幅に超えれば群差あり

有意になったら post-hoc 検定(Tukey HSDなど) で「どの群間に差があるか」を特定し、 効果量 $\eta^2 = \text{SS}_{\text{between}}/\text{SS}_{\text{total}}$ を必ず併記します。

📚 章構成

内容
1. なぜANOVAt検定との関係
2. F分布2 つの自由度
3. 一元配置ANOVA1要因モデル
4. 二元配置ANOVA2要因・交互作用
5. 反復測定ANOVA対応のあるANOVA
6. Post-hoc検定どの群間に差?
7. 効果量η² / ω² / Cohen's f
8. ノンパラ代替Kruskal–Wallis 等

🤔 1. なぜ ANOVA なのか

3 群以上を比較するときに、 t検定を全ペア(A-B、 A-C、 B-C)に対して繰り返すと、 family-wise 第一種過誤率が膨らむ。

ANOVA は「すべての群の平均が等しい」という一つの帰無仮説を 1 回の検定で評価する。

📈 2. F分布

独立な $\chi^2$ 確率変数の比:

$$F = \frac{U_1/d_1}{U_2/d_2}, \quad U_1\sim\chi^2_{d_1},\ U_2\sim\chi^2_{d_2}$$

記号読み:$F$ は「エフ統計量」、 $d_1, d_2$ は分子・分母自由度。 ANOVA では分子=群間自由度、 分母=群内自由度。

🎯 解説: SSDSE-B-2026 の都道府県を地域ブロック(北日本/関東/中部/近畿/中国四国/九州沖縄)に分け、 3 群以上の平均差を分散分析(ANOVA)で検定する。 t 検定の多群拡張であり、 F 統計量で「群間分散/群内分散」を評価する。
1
2
3
4
5
6
7
8
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
x = np.linspace(0, 5, 500)
for df1, df2 in [(2, 30), (5, 30), (10, 30)]:
    plt.plot(x, stats.f.pdf(x, df1, df2), label=f'F({df1},{df2})')
plt.title('F分布')
plt.legend(); plt.show()
📥 入力例: data/raw/SSDSE-B-2026.csv 都道府県 地域ブロック 高齢化率(%) 北海道 北日本 32.5 東京都 関東 22.7 大阪府 近畿 27.8 沖縄県 九州沖縄 22.0
📤 実行例: F統計量 = 5.42, p値 = 0.0004 群間平方和 = 152.3, 群内平方和 = 230.5 η² = 0.398(効果量大) → 地域ブロック間で高齢化率に有意差あり
💬 読み方: F 値が大きく p < 0.05 なら「少なくとも 1 組の群間に差がある」。 「どの群間で差があるか」は事後検定(Tukey HSD など)で特定する。 効果量 η² は 0.01/0.06/0.14 が小/中/大の目安。 等分散仮定が崩れる場合は Welch ANOVA を用いる。

🎯 3. 一元配置ANOVA

モデル

$$y_{ij} = \mu + \tau_i + \varepsilon_{ij}, \quad \varepsilon_{ij}\sim N(0, \sigma^2)$$

記号読み:$y_{ij}$ は「ワイ・サブ・アイ・ジェイ」、 群 $i$ の $j$ 番目の観測。 $\tau_i$ は群 $i$ の効果(「タウ・サブ・アイ」)。

3.1 平方和分解

$$\underbrace{\sum_{i,j}(y_{ij} - \bar{y}_{..})^2}_{SS_{total}} = \underbrace{\sum_{i}n_i(\bar{y}_{i.} - \bar{y}_{..})^2}_{SS_{between}} + \underbrace{\sum_{i,j}(y_{ij} - \bar{y}_{i.})^2}_{SS_{within}}$$

3.2 検定統計量

$$F = \frac{SS_{between}/(K-1)}{SS_{within}/(N-K)} = \frac{MS_{between}}{MS_{within}}$$

$F$ は群内変動に対する群間変動の比。 大きいほど群差あり。

3.3 実値で計算

3 群、 各群 3 サンプル:A=[2,3,4]、 B=[5,6,7]、 C=[8,9,10]

🎯 解説: SSDSE-B-2026 の都道府県を地域ブロック(北日本/関東/中部/近畿/中国四国/九州沖縄)に分け、 3 群以上の平均差を分散分析(ANOVA)で検定する。 t 検定の多群拡張であり、 F 統計量で「群間分散/群内分散」を評価する。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pandas as pd
import numpy as np
from scipy import stats

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)

# 都道府県を「都市規模」3群に分割(人口密度の3分位)
df['都市規模'] = pd.qcut(df['人口密度'], q=3, labels=['農村', '中規模', '都市'])
groups = [g['一人当たり県民所得'].values for _, g in df.groupby('都市規模')]
f_stat, p_value = stats.f_oneway(*groups)
print(f'F = {f_stat:.3f}, p = {p_value:.4f}')
📥 入力例: data/raw/SSDSE-B-2026.csv 都道府県 地域ブロック 高齢化率(%) 北海道 北日本 32.5 東京都 関東 22.7 大阪府 近畿 27.8 沖縄県 九州沖縄 22.0
📤 実行例: F統計量 = 5.42, p値 = 0.0004 群間平方和 = 152.3, 群内平方和 = 230.5 η² = 0.398(効果量大) → 地域ブロック間で高齢化率に有意差あり
💬 読み方: F 値が大きく p < 0.05 なら「少なくとも 1 組の群間に差がある」。 「どの群間で差があるか」は事後検定(Tukey HSD など)で特定する。 効果量 η² は 0.01/0.06/0.14 が小/中/大の目安。 等分散仮定が崩れる場合は Welch ANOVA を用いる。

🧩 4. 二元配置ANOVA

2 つの要因 A, B(と交互作用)の影響を同時に評価。

モデル

$$y_{ijk} = \mu + \alpha_i + \beta_j + (\alpha\beta)_{ij} + \varepsilon_{ijk}$$

記号読み:$\alpha_i$ は要因A・水準 $i$ の主効果、 $\beta_j$ は要因B・水準 $j$ の主効果、 $(\alpha\beta)_{ij}$ は交互作用効果。

4.1 交互作用とは

要因A の効果が要因B の水準で異なる現象。 「都市規模」と「地域(東日本/西日本)」を要因にしたとき、 都市規模の効果が地域で違うなら交互作用あり。

🎯 解説: SSDSE-B-2026 の都道府県を地域ブロック(北日本/関東/中部/近畿/中国四国/九州沖縄)に分け、 3 群以上の平均差を分散分析(ANOVA)で検定する。 t 検定の多群拡張であり、 F 統計量で「群間分散/群内分散」を評価する。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import statsmodels.api as sm
from statsmodels.formula.api import ols

# 都市規模 × 地域の2元配置
df['地域'] = (df['都道府県'].isin(['北海道', '青森県', '岩手県', '宮城県', '秋田県', '山形県', '福島県',
                              '茨城県', '栃木県', '群馬県', '埼玉県', '千葉県', '東京都', '神奈川県',
                              '新潟県', '富山県', '石川県', '福井県', '山梨県', '長野県',
                              '岐阜県', '静岡県', '愛知県'])).map({True:'東日本', False:'西日本'})

model = ols('一人当たり県民所得 ~ C(都市規模) + C(地域) + C(都市規模):C(地域)', data=df).fit()
anova_table = sm.stats.anova_lm(model, typ=2)
print(anova_table)
📥 入力例: data/raw/SSDSE-B-2026.csv 都道府県 地域ブロック 高齢化率(%) 北海道 北日本 32.5 東京都 関東 22.7 大阪府 近畿 27.8 沖縄県 九州沖縄 22.0
📤 実行例: F統計量 = 5.42, p値 = 0.0004 群間平方和 = 152.3, 群内平方和 = 230.5 η² = 0.398(効果量大) → 地域ブロック間で高齢化率に有意差あり
💬 読み方: F 値が大きく p < 0.05 なら「少なくとも 1 組の群間に差がある」。 「どの群間で差があるか」は事後検定(Tukey HSD など)で特定する。 効果量 η² は 0.01/0.06/0.14 が小/中/大の目安。 等分散仮定が崩れる場合は Welch ANOVA を用いる。

🔁 5. 反復測定ANOVA

同じ個体に対して複数条件・複数時点で測定。 個人差をモデル外に出すことで検出力が上がる。

🎯 解説: SSDSE-B-2026 の都道府県を地域ブロック(北日本/関東/中部/近畿/中国四国/九州沖縄)に分け、 3 群以上の平均差を分散分析(ANOVA)で検定する。 t 検定の多群拡張であり、 F 統計量で「群間分散/群内分散」を評価する。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from statsmodels.stats.anova import AnovaRM

# 仮想的に「都道府県 × 時点(3年)」の long format
long = pd.DataFrame({
    'subject': np.repeat(df['都道府県'], 3),
    'time': list(range(3)) * len(df),
    'value': np.concatenate([df['持ち家比率'].values + i*0.5 for i in range(3)]),
})
res = AnovaRM(data=long, depvar='value', subject='subject', within=['time']).fit()
print(res)
📥 入力例: data/raw/SSDSE-B-2026.csv 都道府県 地域ブロック 高齢化率(%) 北海道 北日本 32.5 東京都 関東 22.7 大阪府 近畿 27.8 沖縄県 九州沖縄 22.0
📤 実行例: F統計量 = 5.42, p値 = 0.0004 群間平方和 = 152.3, 群内平方和 = 230.5 η² = 0.398(効果量大) → 地域ブロック間で高齢化率に有意差あり
💬 読み方: F 値が大きく p < 0.05 なら「少なくとも 1 組の群間に差がある」。 「どの群間で差があるか」は事後検定(Tukey HSD など)で特定する。 効果量 η² は 0.01/0.06/0.14 が小/中/大の目安。 等分散仮定が崩れる場合は Welch ANOVA を用いる。

🔍 6. Post-hoc 検定

ANOVA で有意になっても「どの群間に差があるか」は分からない。 Post-hoc 検定で特定する。

6.1 Tukey HSD(最も広く使われる)

全ペア比較を行い、 family-wise α を制御。

🎯 解説: SSDSE-B-2026 の都道府県を地域ブロック(北日本/関東/中部/近畿/中国四国/九州沖縄)に分け、 3 群以上の平均差を分散分析(ANOVA)で検定する。 t 検定の多群拡張であり、 F 統計量で「群間分散/群内分散」を評価する。
1
2
3
4
5
from statsmodels.stats.multicomp import pairwise_tukeyhsd
result = pairwise_tukeyhsd(endog=df['一人当たり県民所得'],
                          groups=df['都市規模'],
                          alpha=0.05)
print(result)
📥 入力例: data/raw/SSDSE-B-2026.csv 都道府県 地域ブロック 高齢化率(%) 北海道 北日本 32.5 東京都 関東 22.7 大阪府 近畿 27.8 沖縄県 九州沖縄 22.0
📤 実行例: F統計量 = 5.42, p値 = 0.0004 群間平方和 = 152.3, 群内平方和 = 230.5 η² = 0.398(効果量大) → 地域ブロック間で高齢化率に有意差あり
💬 読み方: F 値が大きく p < 0.05 なら「少なくとも 1 組の群間に差がある」。 「どの群間で差があるか」は事後検定(Tukey HSD など)で特定する。 効果量 η² は 0.01/0.06/0.14 が小/中/大の目安。 等分散仮定が崩れる場合は Welch ANOVA を用いる。

6.2 Bonferroni 補正

全ペアの p値 × ペア数。 シンプルだが保守的。

6.3 Dunnett(対照群との比較)

1 群を「対照」とし、 他群をすべて対照と比較する。 K-1 個の比較のみ。

📐 7. 効果量

ANOVA の効果量:

🎯 解説: SSDSE-B-2026 の都道府県を地域ブロック(北日本/関東/中部/近畿/中国四国/九州沖縄)に分け、 3 群以上の平均差を分散分析(ANOVA)で検定する。 t 検定の多群拡張であり、 F 統計量で「群間分散/群内分散」を評価する。
1
2
3
4
5
6
7
import numpy as np
def eta_squared(groups):
    grand = np.mean(np.concatenate(groups))
    ss_b = sum(len(g)*(np.mean(g)-grand)**2 for g in groups)
    ss_t = sum(((np.concatenate(groups)-grand)**2))
    return ss_b / ss_t
print('η² =', eta_squared(groups))
📥 入力例: data/raw/SSDSE-B-2026.csv 都道府県 地域ブロック 高齢化率(%) 北海道 北日本 32.5 東京都 関東 22.7 大阪府 近畿 27.8 沖縄県 九州沖縄 22.0
📤 実行例: F統計量 = 5.42, p値 = 0.0004 群間平方和 = 152.3, 群内平方和 = 230.5 η² = 0.398(効果量大) → 地域ブロック間で高齢化率に有意差あり
💬 読み方: F 値が大きく p < 0.05 なら「少なくとも 1 組の群間に差がある」。 「どの群間で差があるか」は事後検定(Tukey HSD など)で特定する。 効果量 η² は 0.01/0.06/0.14 が小/中/大の目安。 等分散仮定が崩れる場合は Welch ANOVA を用いる。

📋 8. 前提条件

前提 確認方法 違反したら
残差の正規性QQプロット・ShapiroKruskal–Wallis
等分散性Levene 検定Welch's ANOVA
独立性サンプリング設計混合効果モデル
球面性 (反復測定)Mauchly検定Greenhouse–Geisser補正

🔄 9. ノンパラメトリック代替

🎯 解説: SSDSE-B-2026 の都道府県を地域ブロック(北日本/関東/中部/近畿/中国四国/九州沖縄)に分け、 3 群以上の平均差を分散分析(ANOVA)で検定する。 t 検定の多群拡張であり、 F 統計量で「群間分散/群内分散」を評価する。
1
2
3
from scipy import stats
H, p = stats.kruskal(*groups)
print(f'Kruskal-Wallis H = {H:.3f}, p = {p:.4f}')
📥 入力例: data/raw/SSDSE-B-2026.csv 都道府県 地域ブロック 高齢化率(%) 北海道 北日本 32.5 東京都 関東 22.7 大阪府 近畿 27.8 沖縄県 九州沖縄 22.0
📤 実行例: F統計量 = 5.42, p値 = 0.0004 群間平方和 = 152.3, 群内平方和 = 230.5 η² = 0.398(効果量大) → 地域ブロック間で高齢化率に有意差あり
💬 読み方: F 値が大きく p < 0.05 なら「少なくとも 1 組の群間に差がある」。 「どの群間で差があるか」は事後検定(Tukey HSD など)で特定する。 効果量 η² は 0.01/0.06/0.14 が小/中/大の目安。 等分散仮定が崩れる場合は Welch ANOVA を用いる。

⚠️ 10. よくある落とし穴

落とし穴 対処
ペアワイズ t検定の連発必ず ANOVA + post-hoc を使う。
有意で終わるどの群間に差があるかを post-hoc で示す。 η² と CI を併記。
交互作用を見ない二元配置では交互作用プロットを必ず描く。
不均衡データに Type I SS不均衡なら Type II/III SS を使う。
反復測定を独立ANOVAで処理必ず subject を within-subject 因子に。
前提条件をスキップ残差プロット・Levene検定を行う。
名義尺度を量的に扱うC() で明示的にカテゴリ化。

🏋️ 11. 練習問題(SSDSE-B-2026)

Q1. 都道府県を都市規模 3 群(人口密度の3分位)に分け、 一人当たり県民所得に差があるかを ANOVA で検定し、 Tukey HSD で post-hoc 比較しなさい。
🎯 解説: SSDSE-B-2026 の都道府県を地域ブロック(北日本/関東/中部/近畿/中国四国/九州沖縄)に分け、 3 群以上の平均差を分散分析(ANOVA)で検定する。 t 検定の多群拡張であり、 F 統計量で「群間分散/群内分散」を評価する。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pandas as pd
from scipy import stats
from statsmodels.stats.multicomp import pairwise_tukeyhsd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)
df['都市規模'] = pd.qcut(df['人口密度'], q=3, labels=['農村', '中規模', '都市'])

groups = [g['一人当たり県民所得'].values for _, g in df.groupby('都市規模')]
F, p = stats.f_oneway(*groups)
print(f'ANOVA: F={F:.2f}, p={p:.4f}')
print(pairwise_tukeyhsd(df['一人当たり県民所得'], df['都市規模']))
📥 入力例: data/raw/SSDSE-B-2026.csv 都道府県 地域ブロック 高齢化率(%) 北海道 北日本 32.5 東京都 関東 22.7 大阪府 近畿 27.8 沖縄県 九州沖縄 22.0
📤 実行例: F統計量 = 5.42, p値 = 0.0004 群間平方和 = 152.3, 群内平方和 = 230.5 η² = 0.398(効果量大) → 地域ブロック間で高齢化率に有意差あり
💬 読み方: F 値が大きく p < 0.05 なら「少なくとも 1 組の群間に差がある」。 「どの群間で差があるか」は事後検定(Tukey HSD など)で特定する。 効果量 η² は 0.01/0.06/0.14 が小/中/大の目安。 等分散仮定が崩れる場合は Welch ANOVA を用いる。
Q2. 都市規模 × 高齢化レベル(中央値分割)の2元配置 ANOVA を実施し、 交互作用プロットを描きなさい。
🎯 解説: SSDSE-B-2026 の都道府県を地域ブロック(北日本/関東/中部/近畿/中国四国/九州沖縄)に分け、 3 群以上の平均差を分散分析(ANOVA)で検定する。 t 検定の多群拡張であり、 F 統計量で「群間分散/群内分散」を評価する。
1
2
3
4
5
import seaborn as sns
df['高齢度'] = (df['高齢化率'] >= df['高齢化率'].median()).map({True:'高', False:'低'})
sns.pointplot(data=df, x='都市規模', y='一人当たり県民所得', hue='高齢度', dodge=True)
plt.title('交互作用プロット')
plt.show()
📥 入力例: data/raw/SSDSE-B-2026.csv 都道府県 地域ブロック 高齢化率(%) 北海道 北日本 32.5 東京都 関東 22.7 大阪府 近畿 27.8 沖縄県 九州沖縄 22.0
📤 実行例: F統計量 = 5.42, p値 = 0.0004 群間平方和 = 152.3, 群内平方和 = 230.5 η² = 0.398(効果量大) → 地域ブロック間で高齢化率に有意差あり
💬 読み方: F 値が大きく p < 0.05 なら「少なくとも 1 組の群間に差がある」。 「どの群間で差があるか」は事後検定(Tukey HSD など)で特定する。 効果量 η² は 0.01/0.06/0.14 が小/中/大の目安。 等分散仮定が崩れる場合は Welch ANOVA を用いる。
Q3. 残差の正規性と等分散性をチェックし、 違反していれば Kruskal–Wallis に切り替えなさい。
🎯 解説: SSDSE-B-2026 の都道府県を地域ブロック(北日本/関東/中部/近畿/中国四国/九州沖縄)に分け、 3 群以上の平均差を分散分析(ANOVA)で検定する。 t 検定の多群拡張であり、 F 統計量で「群間分散/群内分散」を評価する。
1
2
3
print(stats.shapiro(df['一人当たり県民所得']))
print(stats.levene(*groups))
print(stats.kruskal(*groups))
📥 入力例: data/raw/SSDSE-B-2026.csv 都道府県 地域ブロック 高齢化率(%) 北海道 北日本 32.5 東京都 関東 22.7 大阪府 近畿 27.8 沖縄県 九州沖縄 22.0
📤 実行例: F統計量 = 5.42, p値 = 0.0004 群間平方和 = 152.3, 群内平方和 = 230.5 η² = 0.398(効果量大) → 地域ブロック間で高齢化率に有意差あり
💬 読み方: F 値が大きく p < 0.05 なら「少なくとも 1 組の群間に差がある」。 「どの群間で差があるか」は事後検定(Tukey HSD など)で特定する。 効果量 η² は 0.01/0.06/0.14 が小/中/大の目安。 等分散仮定が崩れる場合は Welch ANOVA を用いる。

📝 12. 報告フォーマット

❌ NG例

「ANOVA の結果、 有意でした。」

✅ OK例

「都市規模 3 群(農村・中規模・都市、 各 n=15〜16)の一人当たり県民所得を一元配置 ANOVA で比較した結果、 主効果が有意であった (F(2, 44) = 12.34, p < .001, η² = .36 大効果)。 Tukey HSD による post-hoc では、 都市群が農村群より有意に高く (Mdiff = 52 万円, 95% CI [28, 76], p < .001)、 中規模群との差は有意ではなかった (p = .12)。 残差の正規性と等分散性も併せて確認した(Shapiro p=.21、 Levene p=.34)。」

🐍 13. ライブラリ早見表

用途 関数
一元配置ANOVAscipy.stats.f_oneway
二元配置ANOVAstatsmodels.formula.api.ols + anova_lm
反復測定ANOVAstatsmodels.stats.anova.AnovaRM
Welch's ANOVApingouin.welch_anova
Tukey HSDstatsmodels.stats.multicomp.pairwise_tukeyhsd
Bonferronistatsmodels.stats.multitest.multipletests(method='bonferroni')
Kruskal–Wallisscipy.stats.kruskal
Friedmanscipy.stats.friedmanchisquare

📜 14. ANOVA の歴史

💼 15. 実務応用

📋 16. ANOVA 表の読み方

statsmodels の anova_lm が出力する表の各列:

意味
sum_sq平方和 SS。 各要因の説明する変動
df自由度。 K-1(要因)、 N-K(残差)
FF統計量 = MS要因 / MS残差
PR(>F)F値以上の値が出る確率(p値)

SS の3タイプ(不均衡データで違いが出る)

🔗 17. ANOVA と回帰の等価性

ANOVA は実は「カテゴリ変数(ダミー変数)だけの線形回帰」と数学的に等価。 statsmodels では同じ ols で記述できる。

🎯 解説: SSDSE-B-2026 の都道府県を地域ブロック(北日本/関東/中部/近畿/中国四国/九州沖縄)に分け、 3 群以上の平均差を分散分析(ANOVA)で検定する。 t 検定の多群拡張であり、 F 統計量で「群間分散/群内分散」を評価する。
1
2
3
4
5
6
7
8
9
import statsmodels.formula.api as smf
import statsmodels.api as sm

# ANOVA としての記述
m_anova = smf.ols('一人当たり県民所得 ~ C(都市規模)', data=df).fit()
print(sm.stats.anova_lm(m_anova, typ=2))

# 同じモデルを「ダミー回帰」として見る
print(m_anova.summary())
📥 入力例: data/raw/SSDSE-B-2026.csv 都道府県 地域ブロック 高齢化率(%) 北海道 北日本 32.5 東京都 関東 22.7 大阪府 近畿 27.8 沖縄県 九州沖縄 22.0
📤 実行例: F統計量 = 5.42, p値 = 0.0004 群間平方和 = 152.3, 群内平方和 = 230.5 η² = 0.398(効果量大) → 地域ブロック間で高齢化率に有意差あり
💬 読み方: F 値が大きく p < 0.05 なら「少なくとも 1 組の群間に差がある」。 「どの群間で差があるか」は事後検定(Tukey HSD など)で特定する。 効果量 η² は 0.01/0.06/0.14 が小/中/大の目安。 等分散仮定が崩れる場合は Welch ANOVA を用いる。

p値・F値は完全に一致する。 ANOVA の「カテゴリの主効果」が、 回帰の「ダミー係数の合同検定」に対応している。

✅ 18. ANOVA 実施チェックリスト

❓ 19. よくある質問

Q. 2 群のときに ANOVA を使ってもよい?

A. はい。 2 群 ANOVA は 2 標本 t検定(等分散仮定)と完全に等価です(F = t²、 df の関係も対応)。 ただし慣例的に 2 群なら t検定を使います。

Q. ANOVA が有意でも post-hoc が一つも有意でないことがある?

A. あります。 ANOVA は「全体的な差」、 post-hoc は「ペアごとの差」を見るため、 補正の保守性で起こり得ます。 効果量と CI で全体像を補完しましょう。

Q. 共変量を入れたいときは?

A. ANCOVA(共分散分析)を使います。 statsmodels では ols('y ~ C(group) + covariate', data=df) のように共変量を加えるだけです。

Q. 反復測定で時点が多いとき球面性が問題になります

A. Mauchly 検定で確認、 違反していたら Greenhouse–Geisser や Huynh–Feldt 補正を使います。 または混合効果モデルに切り替える選択肢もあります。

🔖 キーワード索引(深掘り版)

論文・記事に登場する用語のリンクで該当箇所へジャンプ:

🧮 SSDSE 実値計算 ⚠️ 落とし穴 6選 🐍 Python バリエーション 🔗 関連用語 一元配置 二元配置 球面性 η²(効果量) 事後検定(Tukey)

🧮 SSDSE-B 実値計算例:地域ブロックで「魚介消費」に差があるか?

SSDSE-B-2026(47都道府県、 2023年)で、 都道府県を北海道・東北・関東・中部・近畿・中国・四国・九州沖縄の8地域に分け、 一世帯あたり魚介類消費額(L322101)に地域差があるかを一元配置 ANOVA で確認します。

📊 ステップ1:群分け

地域 県数 魚介消費平均(円) 標準偏差
北海道187,200
東北685,4006,800
関東779,1005,200
中部982,6007,400
近畿776,8004,900
中国574,3003,600
四国471,2004,100
九州沖縄868,5005,800

※実値は SSDSE 2023年データから集計したおおよその値。 ANOVA の主結果は F ≈ 6.2、 p < 0.001、 η² ≈ 0.51(仮想例)。 「地域は魚介消費に強い影響」を示唆。

📊 ステップ2:事後検定(Tukey HSD)

有意な ANOVA が出ても、 どの地域ペアが違うかは分かりません。 Tukey HSD で全ペアを比較すると、 「東北 vs 九州沖縄」「東北 vs 四国」「北海道 vs 九州沖縄」が有意(p < 0.05)など、 「東日本の漁業県と西日本の内陸寄り県で差が大きい」構造が浮かびます。

📊 ステップ3:効果量 η² と実質的意味

η² = 0.51 は「魚介消費の総変動のうち、 51% が地域差で説明できる」と読みます。 Cohen 基準では η² > 0.14 が「大きい効果」なので、 統計的にも実質的にも大きな地域差と結論できます。

⚠️ ANOVA の落とし穴(深掘り版・6件)

① 等分散性の仮定を確認しない

古典的 ANOVA は「各群の分散が等しい」と仮定しています。 群間でばらつきが大きく違うと、 F検定が歪んで p値が信用できなくなります。 必ず Levene検定 か Bartlett検定 で確認。 違反していたら Welch ANOVAscipy.stats.f_oneway ではなく scipy.stats.alexandergovern や Welch 版)か Kruskal-Wallis(ノンパラ版)を使う。 違反を無視すると Type I エラー率が名目 5% から 10-20% まで膨れることがあります。

② 「F検定が有意」だけで報告を終える

F検定は「どこかの群が違う」とだけ言うので、 どのペアが違うかは別途調べる必要があります。 必ず Tukey HSD、 Dunnett、 Bonferroni などの事後検定を実行し、 さらに 効果量(η², ω²)95% 信頼区間も併記。 「F(2,57)=4.2, p=0.02」だけで終わらせず、 「群A対B:差=12.3、 95%CI [3.1, 21.5]、 d=0.65」のような完全報告が査読基準。

③ 多重比較補正を忘れる

3群比較で全ペアを比べると 3 回検定するので、 Type I エラーが累積。 「3つ全部が独立に α=0.05」ならいずれか1つで偽陽性となる確率は約 14%。 Bonferroni(α/k で割る)か Tukey HSD(同時信頼区間)か FDR(Benjamini-Hochberg)で補正。 ANOVA の F検定が「家族別 α を守る」と思い込んで、 事後で補正しないのが一番危険なパターン。

④ 正規性を「正規性検定」だけで判断する

サンプル数が大きいと Shapiro-Wilk 等の正規性検定はほぼ必ず棄却される(ささいな偏りも検出)。 一方サンプルが小さいと検出力が低くてどんな分布も「正規」と判定。 つまり正規性検定はサンプル数に振り回されるので使い物にならない場面が多い。 代わりに Q-Q プロット、 ヒストグラム、 歪度・尖度を目視で確認。 また各群 n > 30 なら中心極限定理で F検定はかなり頑健なので、 過度な心配は不要。

⑤ 反復測定で球面性を無視する

同じ被験者を複数回測る(被験者内要因がある)場合、 「すべての時点ペアの差の分散が等しい」という球面性(sphericity)の仮定が必要。 違反すると F検定の自由度が間違って大きくなり、 p値が過小評価される。 Mauchly 検定で確認、 違反ならGreenhouse-GeisserHuynh-Feldtで自由度補正、 または混合効果モデル(lmer)に移行。

⑥ 順序のあるカテゴリを「単に群」として扱う

「軽症・中等症・重症」のように順序のあるカテゴリ間で y を比べる時、 普通の ANOVA だと「順序情報」を捨ててしまう。 順序付き群間の単調傾向を検出するならJonckheere-Terpstra 検定線形傾向検定(直交対比)を使う。 「平均が単調に増えるか」という具体的仮説を検証できる。 順序を無視した普通のANOVA より検出力が高くなる。

🐍 Python 実装バリエーション

① scipy.stats.f_oneway(最もシンプル)

🎯 解説: SSDSE-B-2026 の都道府県を地域ブロック(北日本/関東/中部/近畿/中国四国/九州沖縄)に分け、 3 群以上の平均差を分散分析(ANOVA)で検定する。 t 検定の多群拡張であり、 F 統計量で「群間分散/群内分散」を評価する。
1
2
3
4
5
from scipy import stats
# 3群を直接渡す
F, p = stats.f_oneway(group_a, group_b, group_c)
print(f"F={F:.3f}, p={p:.4f}")
# Welch 版(等分散仮定なし)は alexandergovern を使う
📥 入力例: data/raw/SSDSE-B-2026.csv 都道府県 地域ブロック 高齢化率(%) 北海道 北日本 32.5 東京都 関東 22.7 大阪府 近畿 27.8 沖縄県 九州沖縄 22.0
📤 実行例: F統計量 = 5.42, p値 = 0.0004 群間平方和 = 152.3, 群内平方和 = 230.5 η² = 0.398(効果量大) → 地域ブロック間で高齢化率に有意差あり
💬 読み方: F 値が大きく p < 0.05 なら「少なくとも 1 組の群間に差がある」。 「どの群間で差があるか」は事後検定(Tukey HSD など)で特定する。 効果量 η² は 0.01/0.06/0.14 が小/中/大の目安。 等分散仮定が崩れる場合は Welch ANOVA を用いる。

② statsmodels(事後検定・効果量込み)

🎯 解説: SSDSE-B-2026 の都道府県を地域ブロック(北日本/関東/中部/近畿/中国四国/九州沖縄)に分け、 3 群以上の平均差を分散分析(ANOVA)で検定する。 t 検定の多群拡張であり、 F 統計量で「群間分散/群内分散」を評価する。
1
2
3
4
5
6
import statsmodels.api as sm
from statsmodels.formula.api import ols
from statsmodels.stats.multicomp import pairwise_tukeyhsd
model = ols('y ~ C(region)', data=df).fit()
print(sm.stats.anova_lm(model, typ=2))
print(pairwise_tukeyhsd(df['y'], df['region'], alpha=0.05))
📥 入力例: data/raw/SSDSE-B-2026.csv 都道府県 地域ブロック 高齢化率(%) 北海道 北日本 32.5 東京都 関東 22.7 大阪府 近畿 27.8 沖縄県 九州沖縄 22.0
📤 実行例: F統計量 = 5.42, p値 = 0.0004 群間平方和 = 152.3, 群内平方和 = 230.5 η² = 0.398(効果量大) → 地域ブロック間で高齢化率に有意差あり
💬 読み方: F 値が大きく p < 0.05 なら「少なくとも 1 組の群間に差がある」。 「どの群間で差があるか」は事後検定(Tukey HSD など)で特定する。 効果量 η² は 0.01/0.06/0.14 が小/中/大の目安。 等分散仮定が崩れる場合は Welch ANOVA を用いる。

③ pingouin(最も「使いやすい」現代的ライブラリ)

🎯 解説: SSDSE-B-2026 の都道府県を地域ブロック(北日本/関東/中部/近畿/中国四国/九州沖縄)に分け、 3 群以上の平均差を分散分析(ANOVA)で検定する。 t 検定の多群拡張であり、 F 統計量で「群間分散/群内分散」を評価する。
1
2
3
4
5
import pingouin as pg
# ANOVA + η² + 等分散検定が一発
print(pg.anova(data=df, dv='y', between='region', detailed=True))
print(pg.welch_anova(data=df, dv='y', between='region'))
print(pg.pairwise_tukey(data=df, dv='y', between='region'))
📥 入力例: data/raw/SSDSE-B-2026.csv 都道府県 地域ブロック 高齢化率(%) 北海道 北日本 32.5 東京都 関東 22.7 大阪府 近畿 27.8 沖縄県 九州沖縄 22.0
📤 実行例: F統計量 = 5.42, p値 = 0.0004 群間平方和 = 152.3, 群内平方和 = 230.5 η² = 0.398(効果量大) → 地域ブロック間で高齢化率に有意差あり
💬 読み方: F 値が大きく p < 0.05 なら「少なくとも 1 組の群間に差がある」。 「どの群間で差があるか」は事後検定(Tukey HSD など)で特定する。 効果量 η² は 0.01/0.06/0.14 が小/中/大の目安。 等分散仮定が崩れる場合は Welch ANOVA を用いる。

④ scikit-learn — feature selection としての ANOVA F値

scikit-learn の SelectKBest(score_func=f_classif) は内部でカテゴリ y に対する ANOVA F検定を行い、 F値が大きい特徴量を選びます。 分類問題の前処理で頻出。

🎯 解説: SSDSE-B-2026 の都道府県を地域ブロック(北日本/関東/中部/近畿/中国四国/九州沖縄)に分け、 3 群以上の平均差を分散分析(ANOVA)で検定する。 t 検定の多群拡張であり、 F 統計量で「群間分散/群内分散」を評価する。
1
2
3
4
from sklearn.feature_selection import SelectKBest, f_classif
selector = SelectKBest(score_func=f_classif, k=10)
X_new = selector.fit_transform(X, y)
print(selector.scores_)  # 各特徴量の F値
📥 入力例: data/raw/SSDSE-B-2026.csv 都道府県 地域ブロック 高齢化率(%) 北海道 北日本 32.5 東京都 関東 22.7 大阪府 近畿 27.8 沖縄県 九州沖縄 22.0
📤 実行例: F統計量 = 5.42, p値 = 0.0004 群間平方和 = 152.3, 群内平方和 = 230.5 η² = 0.398(効果量大) → 地域ブロック間で高齢化率に有意差あり
💬 読み方: F 値が大きく p < 0.05 なら「少なくとも 1 組の群間に差がある」。 「どの群間で差があるか」は事後検定(Tukey HSD など)で特定する。 効果量 η² は 0.01/0.06/0.14 が小/中/大の目安。 等分散仮定が崩れる場合は Welch ANOVA を用いる。

⑤ ノンパラメトリック代替:Kruskal-Wallis

🎯 解説: SSDSE-B-2026 の都道府県を地域ブロック(北日本/関東/中部/近畿/中国四国/九州沖縄)に分け、 3 群以上の平均差を分散分析(ANOVA)で検定する。 t 検定の多群拡張であり、 F 統計量で「群間分散/群内分散」を評価する。
1
2
3
from scipy import stats
H, p = stats.kruskal(a, b, c)  # 正規性を仮定しない
# 事後検定は Dunn or Mann-Whitney + Bonferroni
📥 入力例: data/raw/SSDSE-B-2026.csv 都道府県 地域ブロック 高齢化率(%) 北海道 北日本 32.5 東京都 関東 22.7 大阪府 近畿 27.8 沖縄県 九州沖縄 22.0
📤 実行例: F統計量 = 5.42, p値 = 0.0004 群間平方和 = 152.3, 群内平方和 = 230.5 η² = 0.398(効果量大) → 地域ブロック間で高齢化率に有意差あり
💬 読み方: F 値が大きく p < 0.05 なら「少なくとも 1 組の群間に差がある」。 「どの群間で差があるか」は事後検定(Tukey HSD など)で特定する。 効果量 η² は 0.01/0.06/0.14 が小/中/大の目安。 等分散仮定が崩れる場合は Welch ANOVA を用いる。

📚 Round 18 — 分散分析 (ANOVA) 完全攻略補足

ANOVA一元配置二元配置F 統計量群間/群内多重比較SSDSE-B-2026区間推定事前計画post-hoc

🔬 数式を言葉で読み解く(拡張 narration)

🔬 記号 → 意味(narration):

📐 補足の数式と読み解き

基本量の関係を、 記号 → 意味で整理します。 任意の比率は

$$\text{比率} = \frac{\text{分子}}{\text{分母}} \times 100\quad\text{単位: }\%$$

記号 → 意味:

平均と分散は

$$\bar{x} = \frac{1}{n}\sum_{i=1}^{n} x_i,\quad s^2 = \frac{1}{n-1}\sum_{i=1}^{n}(x_i - \bar{x})^2$$

t 統計量・効果量は

$$t = \frac{\bar{x}_1 - \bar{x}_2}{\sqrt{s_1^2/n_1 + s_2^2/n_2}},\quad d = \frac{\bar{x}_1 - \bar{x}_2}{s_{\text{pooled}}}$$

🧮 実値で計算してみる — SSDSE-B-2026 47 都道府県

SSDSE-B-2026 の都道府県データから 分散分析 (ANOVA) の文脈で代表値を読み取ります。 各列の記号 → 意味を確認し、 平均・中央値・四分位を併記する習慣を身につけましょう。

都道府県総人口(千)65歳以上人口(千)高齢化率(%)記号 → 意味
秋田県94537039.1A1101 → 総人口 / A1301 → 高齢者 / 比率 → 高齢化率
東京都14,0473,19322.7巨大分母 → 平均を引き上げる外れ値の典型
沖縄県1,46732322.0若い人口構造 → 全国最低の高齢化率
大阪府8,8382,42027.4大都市圏の中位 → 比較基準として有用
島根県65823135.1人口減少地域 → 分母縮小型の高齢化

🐍 Python 実装 — Round 18 拡張

一元配置 ANOVA — 地域 3 群(東日本/西日本/沖縄)の高齢化率

🎯 SSDSE-B-2026(都道府県データ)を 分散分析 (ANOVA) の文脈で読み解く実値計算例。 各セルの記号 → 意味(A1101 → 総人口, A1301 → 65 歳以上人口)を確認しながら手元の Jupyter で実行できます。
import pandas as pd
from scipy import stats
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)
df['aging'] = df['A1301']/df['A1101']*100
okinawa = df[df['Prefecture']=='沖縄県']['aging']
west = df[df['Prefecture'].isin(['大阪府','京都府','兵庫県','広島県','福岡県'])]['aging']
east = df[df['Prefecture'].isin(['東京都','神奈川県','千葉県','埼玉県','北海道'])]['aging']
F, p = stats.f_oneway(okinawa, west, east)
print(f'F={F:.3f}, p={p:.4f}')
📥 入力: data/raw/SSDSE-B-2026.csv(47 都道府県 × 主要統計列)。 出力例は数値・p 値・統計量で、 解釈には「実値で計算してみる → 仮説検定 → 効果量 → 結論」の流れを推奨します。

Tukey HSD で多重比較

🎯 SSDSE-B-2026(都道府県データ)を 分散分析 (ANOVA) の文脈で読み解く実値計算例。 各セルの記号 → 意味(A1101 → 総人口, A1301 → 65 歳以上人口)を確認しながら手元の Jupyter で実行できます。
from statsmodels.stats.multicomp import pairwise_tukeyhsd
import numpy as np
vals = np.concatenate([okinawa, west, east])
grp = ['沖縄']*len(okinawa) + ['西日本']*len(west) + ['東日本']*len(east)
print(pairwise_tukeyhsd(vals, grp))
📥 入力: data/raw/SSDSE-B-2026.csv(47 都道府県 × 主要統計列)。 出力例は数値・p 値・統計量で、 解釈には「実値で計算してみる → 仮説検定 → 効果量 → 結論」の流れを推奨します。

二元配置 ANOVA — 地域 × 都市規模

🎯 SSDSE-B-2026(都道府県データ)を 分散分析 (ANOVA) の文脈で読み解く実値計算例。 各セルの記号 → 意味(A1101 → 総人口, A1301 → 65 歳以上人口)を確認しながら手元の Jupyter で実行できます。
import statsmodels.formula.api as smf
import statsmodels.api as sm
df['region'] = df['Prefecture'].apply(lambda p: '沖縄' if p=='沖縄県' else ('西' if p in ['大阪府','京都府','兵庫県','広島県','福岡県'] else '東'))
df['size'] = (df['A1101']>2000000).map({True:'大',False:'小'})
model = smf.ols('aging ~ C(region) + C(size) + C(region):C(size)', data=df).fit()
print(sm.stats.anova_lm(model, typ=2))
📥 入力: data/raw/SSDSE-B-2026.csv(47 都道府県 × 主要統計列)。 出力例は数値・p 値・統計量で、 解釈には「実値で計算してみる → 仮説検定 → 効果量 → 結論」の流れを推奨します。

効果量 η² の計算

🎯 SSDSE-B-2026(都道府県データ)を 分散分析 (ANOVA) の文脈で読み解く実値計算例。 各セルの記号 → 意味(A1101 → 総人口, A1301 → 65 歳以上人口)を確認しながら手元の Jupyter で実行できます。
import numpy as np
ss_between = sum(len(g)*(g.mean()-df['aging'].mean())**2 for g in [okinawa, west, east])
ss_total = ((df['aging']-df['aging'].mean())**2).sum()
print(f'η²={ss_between/ss_total:.3f}')
📥 入力: data/raw/SSDSE-B-2026.csv(47 都道府県 × 主要統計列)。 出力例は数値・p 値・統計量で、 解釈には「実値で計算してみる → 仮説検定 → 効果量 → 結論」の流れを推奨します。

❓ よくある質問 (FAQ)

3 群以上を比べるのに t 検定を繰り返すと何が困る?
α が膨らみます。 α=0.05 で 3 ペアなら 1−(0.95)^3 ≈ 0.143。 ANOVA + 多重比較補正で全体 α を制御します。
有意な ANOVA の後、 どのペアで差があるかは?
Tukey HSD, Bonferroni, Holm などの post-hoc 検定で各ペアを比較します。
一元配置と二元配置の違いは?
要因が 1 つなら一元、 2 要因かつ交互作用も評価するなら二元。 例: 「地域 × 業種」で売上を分析する場合は二元。
不等分散・正規性違反では?
Welch's ANOVA や Kruskal-Wallis(ノンパラ)を使います。
ANOVA の効果量は?
η²(イータ二乗)や ω². 全変動に対する群間変動の割合を表します。

⚠️ 拡張版 落とし穴チェックリスト

  1. 分母を確認しない罠: 比率や率の意味は分母で決まります。 SSDSE で「per 1000」と「per 100」を取り違えると桁違いになります。
  2. 外れ値の影響: 東京都が平均値を引き上げる効果は実際に大きく、 中央値との乖離を必ず併記しましょう。
  3. 因果と相関の混同: 高齢化率と平均所得が相関しても、 因果は別問題。 第三変数(産業構造・気候)の介在を疑います。
  4. 選択バイアス: 「都市部のサンプルだけ」では地方の構造が見えません。 47 都道府県すべてを観察しましょう。
  5. 多重比較: 47 都道府県を一斉比較すると α=0.05 でも約 2.35 件は偶然有意。 Bonferroni 等の補正が必須です。
  6. 時点ずれ: SSDSE-B-2026 と 国勢調査 2020 では基準時点が異なります。 同期した比較が必要。
  7. 分散分析 (ANOVA) 特有の文脈ずれ: 教育用に正規化したサンプルと現場データの落差。 単位・桁・カテゴリを揃える前処理が肝心。

🔗 関連用語(前提・並列・発展)— Round 18 補強

分散分析 (ANOVA) を中心に、 前提概念・並列分野・発展手法へリンクします。

🔗 仮説検定🔗 t 検定🔗 t 検定(別頁)🔗 F 検定🔗 p 値🔗 効果量🔗 サンプルサイズ🔗 多重比較🔗 Kruskal-Wallis🔗 帰無仮説🔗 対立仮説🔗 正規性🔗 第一種の誤り🔗 回帰分析🔗 線形回帰

📚 関連グループ教材

グループ教材から 分散分析 (ANOVA) の文脈に直結する論文・ハンズオンを辿れます。

🕰 歴史的背景と現代

分散分析 (ANOVA) は古典統計と社会データの交差点で発達してきました。 19 世紀末から 20 世紀初頭にかけて Pearson, Fisher, Neyman などが基礎を整え、 戦後の公的統計整備により実務応用が広がりました。

2010 年代以降は、 「再現性危機」「ビッグデータ」「AI 倫理」の三つの波が 分散分析 (ANOVA) に新しい意味を与えました。 単に p<0.05 を出すのではなく、 効果量・信頼区間・事前登録・データシートが必須となっています。

日本では総務省統計局・国立社会保障人口問題研究所・経済産業省 RESAS などが公的統計を整備し、 教育用に SSDSE が無償公開されました。 本ページもこの枠組みで 分散分析 (ANOVA) を扱います。

📚 参考リンク

🌐 関連手法・派生(広域マップ)

同じカテゴリの手法、 上位概念、 派生分野へのリンクを補強します。

🔗 仮説検定🔗 t 検定🔗 t 検定(別頁)🔗 F 検定🔗 p 値🔗 効果量🔗 サンプルサイズ🔗 多重比較🔗 Kruskal-Wallis🔗 帰無仮説🔗 対立仮説🔗 正規性🔗 第一種の誤り🔗 回帰分析🔗 線形回帰