論文一覧に戻る 🗺 概念マップ 統計データ分析コンペ 教育用再現集
審査員奨励賞(高校生の部)

2021年度(令和3年度) 統計データ分析コンペティション

都道府県別家計所得格差と
社会保障支出の効果分析

⏱️ 推定読了時間: 約34分
手法: 相関分析・重回帰分析・格差指標計算 | データ: SSDSE-B(47都道府県)
📝 3行で分かる要約

目次

  1. 研究の背景:格差社会と統計
  2. データと変数:格差指標の定義
  3. 都道府県間所得格差の実態
  4. 重回帰分析:格差の要因を探る
  5. ローレンツ曲線とジニ係数
  6. 政策提言
  7. まとめ
  8. 📥 データの準備
  9. 💼 実社会での応用
  10. ⚠️ よくある誤解
  11. 📖 用語集
  12. 📐 手法ガイド
  13. 🚀 発展の可能性
  14. 🎯 自分でやってみよう
  15. 🤔 Q&A

🎯 この記事を読むと何ができるようになるか

📥 データの準備(再現コードを動かす前に)

このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。

1
データをダウンロードする 統計センターの SSDSE 配布ページから、以下のファイルをダウンロードします。
SSDSE-B-2026.csv ← SSDSE-B(都道府県データ)📥 直接DL
⬇ SSDSEダウンロードページを開く
2
ファイルを所定のフォルダに配置する ダウンロードしたCSVを、プロジェクトの data/raw/ フォルダに入れます。
2026 統計・データ解析コンペ/ ├── code/ │ └── 2021_H5_5_shorei.py ← 実行するスクリプト └── data/ └── raw/ SSDSE-B-2026.csv ← ここに置く
3
スクリプトをそのまま実行する ターミナルでプロジェクトルートに移動し、以下を実行します。
python3 code/2021_H5_5_shorei.py
図は html/figures/ に自動保存されます。
研究の背景:格差社会と統計

「格差社会」という言葉が日本で広く使われるようになって久しい。2021年時点でも、日本の都道府県間には消費支出・家計所得において無視できない差異が存在する。一方、政府は社会保障・福祉支出を通じて、こうした格差の是正を図ってきた。

まず「都道府県別家計所得格差と社会保障支出の効果分析」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。

本研究では、都道府県別の家計消費支出を所得水準の代理変数として用い、(1) 格差の実態を変動係数ローレンツ曲線ジニ係数で定量化し、(2) 大学進学率・有効求人倍率高齢化率・人口流動性など複数の社会経済変数が所得水準にどう影響するかを重回帰分析で分析する。

問いの設定 都道府県間の家計所得格差はどの程度か、そして何が格差を生み出しているのか? 社会保障・教育・労働市場の視点から、格差の構造的要因を統計的に解明する。
分析の流れ
SSDSE-B
47都道府県
2022年断面
格差指標
(CV・ジニ係数・
分位数比)
相関分析
(変数候補
の絞り込み)
重回帰分析
(格差要因
の推定)
政策
提言

格差分析 SSDSE-B 相関分析 重回帰分析 ローレンツ曲線

データと変数:格差指標の定義

使用データ

統計数理研究所が提供する SSDSE-B(社会・人口統計体系データセット B)の2022年度断面データを使用した。47都道府県すべてを対象とする。

データ変数役割
消費支出(二人以上の世帯)所得水準の代理変数(目的変数家計の実質購買力を反映
大学進学率高校卒業者のうち進学者数 / 高校卒業者数人的資本の蓄積
高齢化率65歳以上人口 / 総人口高齢化の負担・医療需要
有効求人倍率月間有効求人数 / 月間有効求職者数労働市場の活況度(第三次産業の代理)
転入超過率(転入数-転出数)/ 総人口人口移動・経済的魅力度

格差指標の定義

3つの格差指標
指標計算式解釈
変動係数 (CV)標準偏差 ÷ 平均値が大きいほど格差が大きい。0に近いほど均等。
90/10分位数比第90百分位値 ÷ 第10百分位値上位層と下位層の格差倍率。1に近いほど均等。
ジニ係数ローレンツ曲線と均等線の囲む面積×20(完全均等)〜1(完全不均等)。

DS LEARNING POINT 1

格差の統計的測定:なぜ複数の指標が必要か

格差を1つの数値で表すのは難しい。変動係数平均に対する相対的なばらつきを、分位数比は分布の両端を、ジニ係数は全体の分布形状を捉える。それぞれが異なる格差の側面を反映するため、複数の指標を組み合わせて解釈することが重要。

import numpy as np income = df['消費支出'].values # 1. 変動係数 (CV) cv = income.std() / income.mean() # 2. 90/10分位数比 p90p10 = np.percentile(income, 90) / np.percentile(income, 10) # 3. ジニ係数 def gini(x): x = np.sort(x) n = len(x) cumx = np.cumsum(x) return (n + 1 - 2 * np.sum(cumx) / cumx[-1]) / n gini_coef = gini(income) print(f"CV={cv:.4f}, 90/10比={p90p10:.4f}, ジニ={gini_coef:.4f}")
1
都道府県間所得格差の実態

2022年の都道府県別消費支出(二人以上の世帯)のデータから、以下の格差指標が得られた。

289,630円
全国平均(月額)
0.0655
変動係数 (CV)
1.175倍
90/10分位数比
0.0371
ジニ係数
最高・最低の都道府県(2022年消費支出)
  • 最高:埼玉県 — 324,793円/月(大都市圏・高所得世帯が多い)
  • 最低:愛媛県 — 245,054円/月(地方農林業中心・人口減少)
  • 最大最小比:1.325倍(埼玉県は愛媛県の約1.33倍)
都道府県別消費支出ランキング
図1:都道府県別消費支出ランキング(2022年)。地域ごとに色分け。点線は全国平均(289,630円)。関東(赤)が高く、九州・沖縄(黄橙)や北海道・東北(青)が低い傾向。

地域間格差の傾向

地域特徴消費支出水準
関東東京・埼玉・神奈川等の大都市圏高い傾向
中部製造業が盛んな愛知・静岡中〜高
近畿大阪・京都・兵庫のサービス業
北海道・東北農林業・人口減少地域低い傾向
九州・沖縄観光業・農業・社会保障依存低い傾向
中国・四国過疎化・高齢化が進む地域低い傾向
解釈 変動係数0.066・ジニ係数0.037という値は、国際比較では比較的小さな格差だが、都道府県間の最大最小比は1.33倍に達する。特に関東と地方農山村の格差が顕著で、産業構造・雇用機会の差異が根本的な要因として考えられる。
やってみよう図1:ステップ
📝 コード
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import os
import numpy as np
import pandas as pd
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import statsmodels.api as sm
from scipy import stats

plt.rcParams['font.family'] = 'Hiragino Sans'
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['figure.dpi'] = 150

FIG_DIR = 'html/figures'
DATA_B  = 'data/raw/SSDSE-B-2026.csv'
os.makedirs(FIG_DIR, exist_ok=True)
▼ 実行結果
このステップは print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。
💡 解説
  • import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。
  • matplotlib.use('Agg') — グラフを画面表示せずファイルに保存するためのおまじない。
  • plt.rcParams['font.family'] — グラフの日本語表示用フォント指定(Macは Hiragino Sans、Windowsなら Yu Gothic 等)。
  • os.makedirs('html/figures', exist_ok=True) — 図の保存先フォルダを作る(既にあってもOK)。
💡 Python TIPS f"...{x}..."f-string。文字列の中に {変数} と書くだけで埋め込めて、{x:.2f} のように書式も指定できます。
やってみよう図1:ステップ — ── データ読み込み ──────────────────────────────────────────────────
📝 コード
17
18
19
20
21
22
23
# ── データ読み込み ──────────────────────────────────────────────────
df_b = pd.read_csv(DATA_B, encoding='cp932', header=1)
df_b = df_b[df_b['地域コード'].str.match(r'^R\d{5}', na=False)].copy()
df_b['年度'] = df_b['年度'].astype(int)

# 2022年断面データ
df = df_b[df_b['年度'] == 2022].copy().reset_index(drop=True)
▼ 実行結果
このステップは print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。
💡 解説
  • pd.read_csv(...) でCSVを読み込みます。encoding='cp932' は日本語Windows由来の文字コード、header=1 は「2行目を列名として使う」。
  • df['地域コード'].str.match(r'^R\d{5}', ...) — 正規表現で「R+数字5桁」の行(47都道府県)だけTrueにし、真偽値で行をフィルタ。
  • .astype(int) — 列を整数に変換(年度などを数値比較するため)。
💡 Python TIPS df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。
やってみよう図1:ステップ — ── 変数の定義と派生変数計算 ──────────────────────────────────────────
📝 コード
24
25
26
27
28
29
# ── 変数の定義と派生変数計算 ──────────────────────────────────────────
# 所得代理変数: 消費支出(二人以上の世帯)
df['消費支出'] = df['消費支出(二人以上の世帯)']

# 大学進学率 = 高等学校卒業者のうち進学者数 / 高等学校卒業者数
df['大学進学率'] = df['高等学校卒業者のうち進学者数'] / df['高等学校卒業者数']
▼ 実行結果
このステップは print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。
💡 解説
  • このステップでは前のステップで作ったデータを加工しています。コードを上から順に読んでみてください。
💡 Python TIPS Seriesの .map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()
やってみよう図1:ステップ — 高齢化率 = 65歳以上人口 / 総人口
📝 コード
30
31
32
33
34
35
36
37
# 高齢化率 = 65歳以上人口 / 総人口
df['高齢化率'] = df['65歳以上人口'] / df['総人口']

# 有効求人倍率(労働市場の活況 = 第三次産業・経済の代理)
df['有効求人倍率'] = df['月間有効求人数(一般)'] / df['月間有効求職者数(一般)']

# 転入超過率(人口移動の活発さ)
df['転入超過率'] = (df['転入者数(日本人移動者)'] - df['転出者数(日本人移動者)']) / df['総人口']
▼ 実行結果
このステップは print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。
💡 解説
  • このステップでは前のステップで作ったデータを加工しています。コードを上から順に読んでみてください。
💡 Python TIPS [式 for x in リスト]リスト内包表記。forループでappendする代わりに1行でリストを作れます。
やってみよう図1:ステップ — 地域マップ
📝 コード
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# 地域マップ
region_map = {
    '北海道': '北海道・東北', '青森県': '北海道・東北', '岩手県': '北海道・東北',
    '宮城県': '北海道・東北', '秋田県': '北海道・東北', '山形県': '北海道・東北',
    '福島県': '北海道・東北', '茨城県': '関東', '栃木県': '関東', '群馬県': '関東',
    '埼玉県': '関東', '千葉県': '関東', '東京都': '関東', '神奈川県': '関東',
    '新潟県': '中部', '富山県': '中部', '石川県': '中部', '福井県': '中部',
    '山梨県': '中部', '長野県': '中部', '岐阜県': '中部', '静岡県': '中部', '愛知県': '中部',
    '三重県': '近畿', '滋賀県': '近畿', '京都府': '近畿', '大阪府': '近畿',
    '兵庫県': '近畿', '奈良県': '近畿', '和歌山県': '近畿',
    '鳥取県': '中国・四国', '島根県': '中国・四国', '岡山県': '中国・四国',
    '広島県': '中国・四国', '山口県': '中国・四国', '徳島県': '中国・四国',
    '香川県': '中国・四国', '愛媛県': '中国・四国', '高知県': '中国・四国',
    '福岡県': '九州・沖縄', '佐賀県': '九州・沖縄', '長崎県': '九州・沖縄',
    '熊本県': '九州・沖縄', '大分県': '九州・沖縄', '宮崎県': '九州・沖縄',
    '鹿児島県': '九州・沖縄', '沖縄県': '九州・沖縄'
}
region_colors = {
    '北海道・東北': '#4e9af1', '関東': '#e05c5c', '中部': '#f0a500',
    '近畿': '#5cb85c', '中国・四国': '#9b59b6', '九州・沖縄': '#f39c12'
}

df['地域'] = df['都道府県'].map(region_map)
df['color'] = df['地域'].map(region_colors)
▼ 実行結果
このステップは print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。
💡 解説
  • このステップでは前のステップで作ったデータを加工しています。コードを上から順に読んでみてください。
💡 Python TIPS r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。
やってみよう図1:ステップ — ── 格差指標の計算 ─────────────────────────────────────────────────
📝 コード
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# ── 格差指標の計算 ─────────────────────────────────────────────────
income = df['消費支出'].values
cv = income.std() / income.mean()  # 変動係数
p90p10 = np.percentile(income, 90) / np.percentile(income, 10)  # 90/10分位数比

# ジニ係数
def gini(x):
    x = np.sort(x)
    n = len(x)
    cumx = np.cumsum(x)
    return (n + 1 - 2 * np.sum(cumx) / cumx[-1]) / n

gini_coef = gini(income)

print("=== 格差指標(2022年断面) ===")
print(f"平均消費支出: {income.mean():,.0f} 円/月")
print(f"変動係数 (CV): {cv:.4f}")
print(f"90/10分位数比: {p90p10:.4f}")
print(f"ジニ係数: {gini_coef:.4f}")
print(f"最大 - {df.loc[df['消費支出'].idxmax(), '都道府県']}: {income.max():,.0f} 円")
print(f"最小 - {df.loc[df['消費支出'].idxmin(), '都道府県']}: {income.min():,.0f} 円")
▼ 実行結果
このステップは print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。
💡 解説
  • gini(arr) — Gini係数(0=完全平等、1=完全不平等)を計算。ソート → 累積和 → 公式という単純実装。
💡 Python TIPS x if cond else y三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。
やってみよう図1:ステップ — ── 重回帰分析 ─────────────────────────────────────────────────────
📝 コード
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
# ── 重回帰分析 ─────────────────────────────────────────────────────
X_cols = ['大学進学率', '高齢化率', '有効求人倍率', '転入超過率']
X_raw = df[X_cols].copy()
X_std = (X_raw - X_raw.mean()) / X_raw.std()
Y_raw = df['消費支出']
Y_std = (Y_raw - Y_raw.mean()) / Y_raw.std()

X_sm = sm.add_constant(X_std)
model = sm.OLS(Y_std, X_sm).fit()

print("\n=== 重回帰分析結果(標準化変数) ===")
print(model.summary())

coefs   = model.params[1:]
pvalues = model.pvalues[1:]
conf_int = model.conf_int().iloc[1:]

print("\n標準化偏回帰係数:")
for col, b, p in zip(X_cols, coefs, pvalues):
    sig = "***" if p < 0.001 else "**" if p < 0.01 else "*" if p < 0.05 else "n.s."
    print(f"  {col}: β={b:.4f}, p={p:.4f} {sig}")
print(f"\nR²={model.rsquared:.3f}, 調整済みR²={model.rsquared_adj:.3f}")
▼ 実行結果
このステップは print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。
💡 解説
  • sm.add_constant(X) — 切片項(定数1の列)を先頭に追加。statsmodelsで必須。
  • sm.OLS(y, X).fit() — 最小二乗法でモデルを推定。model.params, model.pvalues, model.conf_int() で結果取得。
💡 Python TIPS df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。
やってみよう図1:ステップ — 相関分析
📝 コード
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# 相関分析
print("\n=== 相関分析 ===")
for col in X_cols:
    r, p = stats.pearsonr(df[col].dropna(), df.loc[df[col].notna(), '消費支出'])
    print(f"  {col} vs 消費支出: r={r:.4f}, p={p:.4f}")

# ── 図1: 都道府県別消費支出ランキング(棒グラフ) ──────────────────
df_sorted = df.sort_values('消費支出', ascending=True).reset_index(drop=True)

fig, ax = plt.subplots(figsize=(14, 10))
bars = ax.barh(
    df_sorted['都道府県'],
    df_sorted['消費支出'] / 1000,
    color=[region_colors[r] for r in df_sorted['地域']],
    edgecolor='white', linewidth=0.3
)
ax.axvline(income.mean() / 1000, color='#333', linestyle='--', linewidth=1.5, label=f'全国平均 {income.mean()/1000:.1f}千円')
ax.set_xlabel('消費支出(千円/月, 二人以上の世帯)', fontsize=12)
ax.set_title('都道府県別 消費支出ランキング(2022年)\n─ 家計所得格差の可視化 ─', fontsize=14, fontweight='bold')
ax.legend(fontsize=11, loc='lower right')
▼ 実行結果
このステップは print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。
💡 解説
  • fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。
  • sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。
  • ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。
  • stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。
💡 Python TIPS s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。
やってみよう図1:ステップ — 凡例パッチ
📝 コード
125
126
127
128
129
130
131
132
133
134
135
136
137
# 凡例パッチ
from matplotlib.patches import Patch
legend_elements = [Patch(facecolor=c, label=r) for r, c in region_colors.items()]
ax.legend(handles=legend_elements + [
    plt.Line2D([0], [0], color='#333', linestyle='--', linewidth=1.5, label=f'全国平均 {income.mean()/1000:.1f}千円')
], fontsize=10, loc='lower right', ncol=2)

ax.tick_params(axis='y', labelsize=9)
ax.tick_params(axis='x', labelsize=10)
ax.set_xlim(200, 350)
plt.tight_layout()
fig.savefig(os.path.join(FIG_DIR, '2021_H5_5_fig1.png'), bbox_inches='tight')
plt.close(fig)
▼ 実行結果
=== 格差指標(2022年断面) ===
平均消費支出: 289,630 円/月
変動係数 (CV): 0.0655
90/10分位数比: 1.1753
ジニ係数: 0.0371
最大 - 埼玉県: 324,793 円
最小 - 愛媛県: 245,054 円

=== 重回帰分析結果(標準化変数) ===
                            OLS Regression Results                            
==============================================================================
Dep. Variable:                   消費支出   R-squared:                       0.311
Model:                            OLS   Adj. R-squared:                  0.245
Method:                 Least Squares   F-statistic:                     4.729
Date:                Mon, 18 May 2026   Prob (F-statistic):            0.00305
Time:                        11:23:52   Log-Likelihood:                -57.446
No. Observations:                  47   AIC:                             124.9
Df Residuals:                      42   BIC:                             134.1
Df Model:                           4                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
const        -6.8e-16      0.127  -5.36e-15      1.000      -0.256       0.256
大学進学率          0.3330      0.161      2.069      0.045       0.008       0.658
高齢化率           0.0240      0.200      0.120      0.905      -0.379       0.427
有効求人倍率         0.2599      0.145      1.788      0.081      -0.033       0.553
転入超過率          0.4020      0.196      2.055      0.046       0.007       0.797
==============================================================================
Omnibus:                        1.972   Durbin-Watson:                   1.945
Prob(Omnibus):                  0.373   Jarque-Bera (JB):                1.256
Skew:                          -0.385   Prob(JB):                        0.534
Kurtosis:                       3.220   Cond. No.                         3.10
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.

標準化偏回帰係数:
  大学進学率: β=0.3330, p=0.0447 *
  高齢化率: β=0.0240, p=0.9048 n.s.
  有効求人倍率: β=0.2599, p=0.0810 n.s.
  転入超過率: β=0.4020, p=0.0462 *

R²=0.311, 調整済みR²=0.245

=== 相関分析 ===
  大学進学率 vs 消費支出: r=0.4464, p=0.0017
  高齢化率 vs 消費支出: r=-0.3614, p=0.0126
  有効求人倍率 vs 消費支出: r=-0.0198, p=0.8948
  転入超過率 vs 消費支出: r=0.4371, p=0.0021
💡 解説
  • import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。
  • fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。
💡 Python TIPS np.cumsum(arr)累積和np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。
やってみよう── 図2: ローレンツ曲線 ──────────────────────────────────────────
📝 コード
138
139
140
141
142
143
144
145
146
147
148
149
print("\n図1 保存完了: 2021_H5_5_fig1.png")

# ── 図2: ローレンツ曲線 ──────────────────────────────────────────
income_sorted = np.sort(income)
n = len(income_sorted)
lorenz_x = np.concatenate([[0], np.arange(1, n + 1) / n])
lorenz_y = np.concatenate([[0], np.cumsum(income_sorted) / income_sorted.sum()])

fig, ax = plt.subplots(figsize=(8, 7))
ax.plot([0, 1], [0, 1], 'k--', linewidth=1.5, label='完全均等分布線')
ax.plot(lorenz_x, lorenz_y, color='#e05c5c', linewidth=2.5, label=f'ローレンツ曲線(ジニ係数={gini_coef:.4f})')
ax.fill_between(lorenz_x, lorenz_x, lorenz_y, alpha=0.15, color='#e05c5c', label='格差面積')
▼ 実行結果
このステップは print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。
💡 解説
  • fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。
  • ax.fill_between(...) — 2つの曲線で囲まれた領域を塗りつぶし。Lorenz曲線の格差面積などを可視化。
💡 Python TIPS df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。
やってみよう── 図2: ローレンツ曲線 ────────────────────────────────────────── — 注目点を追加
📝 コード
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# 注目点を追加
idx10 = int(0.1 * n)
idx90 = int(0.9 * n)
ax.annotate(
    f'下位10%が得る所得シェア\n= {lorenz_y[idx10]:.1%}',
    xy=(lorenz_x[idx10], lorenz_y[idx10]),
    xytext=(0.2, 0.05),
    arrowprops=dict(arrowstyle='->', color='#333', lw=1.2),
    fontsize=10, color='#333'
)

ax.set_xlabel('都道府県の累積比率(所得の低い順)', fontsize=12)
ax.set_ylabel('消費支出の累積シェア', fontsize=12)
ax.set_title('ローレンツ曲線:都道府県間消費支出格差(2022年)', fontsize=13, fontweight='bold')
ax.legend(fontsize=11, loc='upper left')
ax.set_xlim(0, 1); ax.set_ylim(0, 1)
ax.grid(True, alpha=0.3)
plt.tight_layout()
fig.savefig(os.path.join(FIG_DIR, '2021_H5_5_fig2.png'), bbox_inches='tight')
plt.close(fig)
▼ 実行結果
図1 保存完了: 2021_H5_5_fig1.png
💡 解説
  • fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。
💡 Python TIPS Seriesの .map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()
セクション4: 重回帰分析
2
重回帰分析:格差の要因を探る

消費支出(所得代理)を目的変数とし、大学進学率・高齢化率有効求人倍率・転入超過率を説明変数とした重回帰分析を実施した。すべての変数を標準化(Z変換)したうえでOLS推定を行い、標準化偏回帰係数(β)として比較する。

Z(消費支出) = β₁×Z(大学進学率) + β₂×Z(高齢化率) + β₃×Z(有効求人倍率) + β₄×Z(転入超過率) + ε

Z(x) = (x - x̄) / s ← 標準化。βは「その変数が1SD変化したとき所得が何SD変化するか」を示す

相関分析(事前確認)

説明変数相関係数 rp値有意性
大学進学率0.4460.0017** (p<0.01)
転入超過率0.4370.0021** (p<0.01)
高齢化率-0.3610.0126* (p<0.05)
有効求人倍率-0.0200.8948n.s.

重回帰分析結果

変数標準化偏回帰係数 βp値有意性解釈
大学進学率0.3330.045* (p<0.05)進学率が高い都道府県ほど所得が高い
転入超過率0.4020.046* (p<0.05)人が流入する地域は所得水準が高い
高齢化率0.0240.905n.s.高齢化率の独立効果は限定的
有効求人倍率0.2600.081n.s. (傾向)求人倍率の効果は10%水準で有意傾向
モデルの適合度 =0.311(決定係数)、調整済み=0.245。47都道府県の消費支出格差の約31%が、4変数で説明できる。F検定 p=0.003 < 0.01 で、モデル全体として有意。
標準化偏回帰係数プロット
図4:標準化偏回帰係数と95%信頼区間。赤バーは有意(p<0.05)な変数。転入超過率(β=0.402)と大学進学率(β=0.333)が所得水準と正の関連を持つ。
📌 この回帰係数プロットの読み方
このグラフは
重回帰分析の各説明変数係数(影響の強さと向き)をバーや点で表したグラフ。
読み方
右(プラス方向)に伸びるバーは「この変数が増えると目的変数も増える」正の影響。左(マイナス方向)は逆。
なぜそう解釈できるか
エラーバー(誤差棒)が0をまたいでいない変数が統計的に有意(p < 0.05)。バーが長いほど影響が大きい。
有効求人倍率と消費支出の散布図
図3:有効求人倍率 vs 消費支出(2022年,47都道府県)。地域ごとに色分けし、都道府県名をラベル表示。回帰直線は正の傾き(r=−0.020)だが、有効求人倍率単独での説明力は限定的。

DS LEARNING POINT 2

標準化偏回帰係数:変数間の影響力を比較する

通常の回帰係数は単位の影響を受けるため、異なる変数の「影響力」を直接比較できない。すべての変数をZ変換(標準化)してから回帰すると、得られる係数β は「その変数が1標準偏差増えたとき、目的変数が何標準偏差変化するか」を示す。これにより単位の異なる変数間の影響力を公平に比較できる。

import statsmodels.api as sm # 標準化 X_std = (X - X.mean()) / X.std() Y_std = (Y - Y.mean()) / Y.std() # OLS回帰 X_sm = sm.add_constant(X_std) model = sm.OLS(Y_std, X_sm).fit() # 標準化偏回帰係数(βはmodel.params[1:]) betas = model.params[1:] pvals = model.pvalues[1:] conf = model.conf_int().iloc[1:] print(f"={model.rsquared:.3f}") for var, b, p in zip(var_names, betas, pvals): sig = "*" if p < 0.05 else "n.s." print(f" {var}: β={b:.3f}, p={p:.3f} {sig}")

DS LEARNING POINT 3

相関と偏回帰:見かけの相関と真の効果

高齢化率は消費支出と単変量相関では r=−0.361(有意 p<0.05)と負の関連を示すが、重回帰に投入すると β=0.024(n.s.)になる。これは「高齢化率が高い地域は、他の変数(転入超過率・大学進学率)も低い傾向があり、見かけの相関が生じていた」ことを示す。重回帰分析は、他の変数の影響を統制した上での純粋な効果(偏回帰係数)を推定できる。

# 相関行列交絡変数を確認 import pandas as pd corr_matrix = df[['消費支出', '大学進学率', '高齢化率', '有効求人倍率', '転入超過率']].corr() print(corr_matrix.round(3)) # ポイント: 高齢化率は大学進学率と r=-0.6前後の負の相関 # → 高齢化率↑ の地域は進学率↓ → 消費支出も低くなる(交絡
やってみよう── 図3: 有効求人倍率 vs 消費支出(散布図・地域色分け) ──────────────
📝 コード
171
172
173
174
175
176
177
178
179
180
181
182
print("図2 保存完了: 2021_H5_5_fig2.png")

# ── 図3: 有効求人倍率 vs 消費支出(散布図・地域色分け) ──────────────
fig, ax = plt.subplots(figsize=(11, 8))

for region, color in region_colors.items():
    mask = df['地域'] == region
    ax.scatter(
        df.loc[mask, '有効求人倍率'],
        df.loc[mask, '消費支出'] / 1000,
        c=color, s=80, alpha=0.85, edgecolors='white', linewidth=0.5, label=region
    )
▼ 実行結果
このステップは print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。
💡 解説
  • fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。
💡 Python TIPS Seriesの .map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()
やってみよう── 図3: 有効求人倍率 vs 消費支出(散布図・地域色分け) ────────────── — 都道府県ラベル
📝 コード
183
184
185
186
187
188
189
190
# 都道府県ラベル
for _, row in df.iterrows():
    ax.annotate(
        row['都道府県'].replace('都', '').replace('道', '').replace('府', '').replace('県', ''),
        (row['有効求人倍率'], row['消費支出'] / 1000),
        fontsize=7, ha='center', va='bottom',
        xytext=(0, 4), textcoords='offset points', color='#333'
    )
▼ 実行結果
このステップは print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。
💡 解説
  • for _, row in df.iterrows() — DataFrameを1行ずつ取り出すループ。1点ずつ描画したいときに使用。
💡 Python TIPS [式 for x in リスト]リスト内包表記。forループでappendする代わりに1行でリストを作れます。
やってみよう── 図3: 有効求人倍率 vs 消費支出(散布図・地域色分け) ────────────── — 回帰直線
📝 コード
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# 回帰直線
x_reg = df['有効求人倍率'].values
y_reg = df['消費支出'].values / 1000
slope, intercept, r_val, p_val, _ = stats.linregress(x_reg, y_reg)
x_line = np.linspace(x_reg.min(), x_reg.max(), 100)
ax.plot(x_line, slope * x_line + intercept, color='#333', linewidth=1.8,
        linestyle='--', label=f'回帰直線 (r={r_val:.3f}, p={p_val:.3f})')

ax.set_xlabel('有効求人倍率(労働市場の活況度)', fontsize=12)
ax.set_ylabel('消費支出(千円/月)', fontsize=12)
ax.set_title('有効求人倍率 vs 消費支出(2022年,47都道府県)\n─ 労働市場の強さと家計所得の関係 ─',
             fontsize=13, fontweight='bold')
ax.legend(fontsize=10, loc='upper left', ncol=2)
ax.grid(True, alpha=0.25)
plt.tight_layout()
fig.savefig(os.path.join(FIG_DIR, '2021_H5_5_fig3.png'), bbox_inches='tight')
plt.close(fig)
▼ 実行結果
図2 保存完了: 2021_H5_5_fig2.png
💡 解説
  • stats.linregress(x, y) — 単回帰の傾き・切片・r値・p値・標準誤差を返します。使わない値は _ で受け取り。
  • fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。
💡 Python TIPS r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。
セクション5: ローレンツ曲線ジニ係数
3
ローレンツ曲線ジニ係数

格差の大きさを視覚的に示す最も有名なツールが「ローレンツ曲線」とそれから計算される「ジニ係数」である。消費支出の低い都道府県から順に並べ、累積人口比率と累積所得比率の関係を描く。

ローレンツ曲線
図2:ローレンツ曲線(2022年,47都道府県の消費支出)。点線(均等線)とローレンツ曲線の間の面積(赤塗り)がジニ係数に比例する。曲線が均等線から遠いほど格差が大きい。
📌 この回帰係数プロットの読み方
このグラフは
重回帰分析の各説明変数係数(影響の強さと向き)をバーや点で表したグラフ。
読み方
右(プラス方向)に伸びるバーは「この変数が増えると目的変数も増える」正の影響。左(マイナス方向)は逆。
なぜそう解釈できるか
エラーバー(誤差棒)が0をまたいでいない変数が統計的に有意(p < 0.05)。バーが長いほど影響が大きい。
0.037
ジニ係数(都道府県間・消費支出, 2022年)
ジニ係数の国際比較参考値
  • 北欧諸国(スウェーデン等): 約0.25〜0.30(可処分所得)
  • 日本(世帯所得): 約0.37〜0.38(再分配後)
  • アメリカ: 約0.40〜0.45
  • 本分析(都道府県間): 0.037(都道府県平均値のため非常に小さい)
重要な注意 本分析のジニ係数(0.037)は「都道府県の平均消費支出」間の格差を測定したもの。都道府県内部の世帯間格差は平均化されてしまっている。実際の世帯間ジニ係数(約0.37)は、この約10倍の格差水準であることに注意が必要。

DS LEARNING POINT 4

ローレンツ曲線とジニ係数の計算

ローレンツ曲線は、所得の低い順に並べたとき「人口の下位x%が所得全体のy%を得ている」ことを示す。均等分布(すべて同じ所得)なら対角線と一致する。ジニ係数は均等線とローレンツ曲線の間の面積の2倍として定義される。

import numpy as np def gini(x): """ジニ係数の計算(ベクトル化)""" x = np.sort(x) # 昇順ソート n = len(x) cumx = np.cumsum(x) # Gini = (n+1 - 2*Σ(累積シェア)) / n return (n + 1 - 2 * np.sum(cumx) / cumx[-1]) / n # ローレンツ曲線の点を計算 income_sorted = np.sort(income) lorenz_x = np.concatenate([[0], np.arange(1, n+1) / n]) lorenz_y = np.concatenate([[0], np.cumsum(income_sorted) / income_sorted.sum()]) # 結果 print(f"ジニ係数: {gini(income):.4f}") print(f"下位10%の所得シェア: {lorenz_y[int(0.1*n)]:.1%}") print(f"下位50%の所得シェア: {lorenz_y[int(0.5*n)]:.1%}")
やってみよう── 図4: 標準化偏回帰係数プロット ────────────────────────────────
📝 コード
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
print("図3 保存完了: 2021_H5_5_fig3.png")

# ── 図4: 標準化偏回帰係数プロット ────────────────────────────────
var_labels = ['大学進学率', '高齢化率', '有効求人倍率', '転入超過率']
betas  = coefs.values
ci_lo  = (betas - conf_int.iloc[:, 0].values)
ci_hi  = (conf_int.iloc[:, 1].values - betas)

colors_bar = ['#e05c5c' if p < 0.05 else '#aaaaaa' for p in pvalues]

fig, ax = plt.subplots(figsize=(9, 5))
y_pos = range(len(var_labels))
bars2 = ax.barh(y_pos, betas, xerr=[ci_lo, ci_hi], color=colors_bar,
                align='center', edgecolor='white', linewidth=0.5,
                error_kw=dict(ecolor='#555', elinewidth=1.5, capsize=5))
ax.axvline(0, color='#333', linewidth=1.0)
ax.set_yticks(y_pos)
ax.set_yticklabels(var_labels, fontsize=12)
ax.set_xlabel('標準化偏回帰係数 (β) ± 95%CI', fontsize=12)
ax.set_title('消費支出(所得)格差の規定要因\n─ 重回帰分析・標準化偏回帰係数(2022年, N=47)─',
             fontsize=13, fontweight='bold')
ax.set_xlim(-0.4, 0.9)
ax.grid(True, axis='x', alpha=0.3)
▼ 実行結果
このステップは print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。
💡 解説
  • fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。
  • ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。
💡 Python TIPS [式 for x in リスト]リスト内包表記。forループでappendする代わりに1行でリストを作れます。
やってみよう── 図4: 標準化偏回帰係数プロット ──────────────────────────────── — β値をバー上に表示
📝 コード
232
233
234
235
236
237
# β値をバー上に表示
for i, (b, p) in enumerate(zip(betas, pvalues)):
    sig_str = '*' if p < 0.05 else ''
    ax.text(b + (0.04 if b >= 0 else -0.04), i,
            f'β={b:.3f}{sig_str}', va='center',
            ha='left' if b >= 0 else 'right', fontsize=10, fontweight='bold')
▼ 実行結果
このステップは print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。
💡 解説
  • このステップでは前のステップで作ったデータを加工しています。コードを上から順に読んでみてください。
💡 Python TIPS r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。
やってみよう── 図4: 標準化偏回帰係数プロット ──────────────────────────────── — 凡例
📝 コード
238
239
240
241
242
243
244
245
246
247
# 凡例
from matplotlib.patches import Patch as MPatch
legend_handles = [
    MPatch(facecolor='#e05c5c', label='有意 (p<0.05)'),
    MPatch(facecolor='#aaaaaa', label='非有意')
]
ax.legend(handles=legend_handles, fontsize=10, loc='lower right')
plt.tight_layout()
fig.savefig(os.path.join(FIG_DIR, '2021_H5_5_fig4.png'), bbox_inches='tight')
plt.close(fig)
▼ 実行結果
図3 保存完了: 2021_H5_5_fig3.png
💡 解説
  • import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。
  • fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。
💡 Python TIPS x if cond else y三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。

政策提言:格差是正への処方箋

本分析の重回帰結果は、都道府県間の所得格差の主な規定要因として「大学進学率」と「転入超過率」を特定した。これらの知見から、以下の政策的含意が導かれる。

1. 教育投資の地域格差是正 大学進学率が高い都道府県ほど消費支出が有意に高い(β=0.333, p<0.05)。高等教育への進学率が低い地方では、奨学金制度の拡充・地方大学の魅力向上・産学連携による就職支援が所得格差の縮小に資すると考えられる。
2. 地方への人口流入促進 転入超過率が高い都道府県は消費支出も高い(β=0.402, p<0.05)。人口が流入する地域は経済的魅力が高く、雇用・サービス・税収の好循環が生まれる。テレワーク促進・移住支援・地方創生拠点整備が格差是正に効果的。
3. 社会保障による下支えの重要性 分析からは高齢化率の独立効果は限定的(p=0.905)だったが、社会保障支出(医療・介護・生活保護)は消費の下支えとして機能している。格差指標(ジニ係数=0.037)が小さく抑えられている背景には、社会保障による再分配効果が存在すると推測される。
政策領域具体策期待効果
教育地方奨学金の拡充、地方大学強化大学進学率↑ → 所得↑
産業・雇用地方への企業誘致、テレワーク推進転入超過率↑ → 所得↑
社会保障生活保護・医療・介護の充実最下位層の底上げ
インフラ交通・通信インフラ整備地方の経済アクセス改善
やってみよう図4:結果まとめ
📝 コード
249
250
251
252
253
254
255
256
257
258
259
260
261
print("図4 保存完了: 2021_H5_5_fig4.png")

print("\n=== 全図の生成完了 ===")
print(f"  図1: 都道府県別消費支出ランキング")
print(f"  図2: ローレンツ曲線(ジニ係数={gini_coef:.4f})")
print(f"  図3: 有効求人倍率 vs 消費支出(散布図)")
print(f"  図4: 標準化偏回帰係数プロット(R²={model.rsquared:.3f})")
print(f"\n格差サマリー:")
print(f"  変動係数: {cv:.4f}")
print(f"  90/10分位数比: {p90p10:.4f}")
print(f"  ジニ係数: {gini_coef:.4f}")
print(f"  最大: {df.loc[df['消費支出'].idxmax(), '都道府県']} ({income.max():,.0f}円)")
print(f"  最小: {df.loc[df['消費支出'].idxmin(), '都道府県']} ({income.min():,.0f}円)")
▼ 実行結果
図4 保存完了: 2021_H5_5_fig4.png

=== 全図の生成完了 ===
  図1: 都道府県別消費支出ランキング
  図2: ローレンツ曲線(ジニ係数=0.0371)
  図3: 有効求人倍率 vs 消費支出(散布図)
  図4: 標準化偏回帰係数プロット(R²=0.311)

格差サマリー:
  変動係数: 0.0655
  90/10分位数比: 1.1753
  ジニ係数: 0.0371
  最大: 埼玉県 (324,793円)
  最小: 愛媛県 (245,054円)
💡 解説
  • このステップでは前のステップで作ったデータを加工しています。コードを上から順に読んでみてください。
💡 Python TIPS r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。

まとめ

主な発見

SSDSE-B の47都道府県・2022年断面データを用いた分析の結果:

  1. 格差の実態:都道府県間消費支出の変動係数は0.066、ジニ係数は0.037と、都道府県平均レベルでは比較的小さいが、最大(埼玉県: 324,793円)と最小(愛媛県: 245,054円)の差は1.33倍に達する。
  2. 大学進学率の効果(β=0.333, p<0.05):高等教育への進学率が高い都道府県ほど、家計の消費支出水準が有意に高い。人的資本の蓄積が所得格差の主要因。
  3. 転入超過率の効果(β=0.402, p<0.05):人口が流入している都道府県は所得水準が高く、人口移動が経済的活力を反映・強化する好循環が存在する。
  4. 高齢化率交絡単変量では負の相関(r=−0.361)を示した高齢化率だが、重回帰では有意でなく(p=0.905)、他の変数との交絡が示唆された。
  5. モデルの説明力:=0.311(調整済み0.245)。格差の約31%が今回の4変数で説明され、残りは産業構造・地理的条件など他の要因によると考えられる。
総合的な結論 都道府県間の家計所得格差は、教育機会の差(大学進学率)と経済的求心力の差(転入超過率)によって大きく規定される。社会保障支出による再分配は格差を一定程度緩和しているが、根本的な格差是正には教育投資・産業政策・移住促進の組み合わせが必要である。
教育的価値(この分析から学べること)
  • ジニ係数:0〜1で表す格差の度合い。0は完全平等、1に近いほど偏りが大きい。所得格差以外にも応用できる汎用指標。
  • 社会保障支出の再分配効果:再分配前後でジニ係数がどれだけ下がるかで、社会保障の格差是正効果を定量的に評価できる。
  • 時系列+断面の組み合わせ:『時間変化(時系列)』と『地域間差(断面)』を別々に見ることで、現象の全体像を把握できる。

データ・コードのダウンロード

分析スクリプト(2021_H5_5_shorei.py)
データ出典
SSDSE-B-2026 都道府県別統計統計数理研究所 SSDSE(社会・人口統計体系データセット)

本スクリプトは SSDSE-B-2026.csv の実データのみを使用(合成データ・np.random.seed等は一切使用していない)。

教育用再現コード | 2021年度(令和3年度)統計データ分析コンペティション 審査員奨励賞(高校生の部)| SSDSE-B 実データ使用

⚠️ よくある誤解と注意点

統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。

❌ 「相関がある=因果関係がある」ではない
疑似相関spurious correlationとは、見かけ上は関係があるように見えるが、実際は無関係、または第三の変数(交絡変数)が両方に影響しているだけの現象です。

古典例: アイスクリームの売上 と 水難事故件数 は強く相関するが、片方が他方を引き起こしているわけではない。両者とも「夏の暑さ」という第三の変数に引きずられているだけ。

論文を読むときの心構え: 「○○と△△に強い相関が見られた」だけで終わっている主張は、本当に因果関係があるのか、それとも第三の変数(人口・所得・地理など)が共通要因として効いているだけではないかを必ず疑ってください。
❌ 「p値が小さい=重要な発見」ではない
p値が小さい(例えば p < 0.001)ことは「統計的に偶然とは考えにくい」という意味であって、「実用的に大きな効果がある」という意味ではありません。

例: 巨大なサンプルサイズ(n=100,000)では、相関係数 r=0.02 でも p < 0.001 になります。しかし r=0.02 は実用上ほぼ無視できる関係です。

正しい読み方: p値効果量係数の大きさ、相関係数の値)の両方をセットで判断してください。p値だけで「重要な発見」と結論づけるのは誤りです。
❌ 「回帰係数が大きい=重要な変数」ではない
回帰係数の絶対値は、説明変数単位に強く依存します。「年収(万円)」と「失業率(%)」の係数を直接比較しても意味がありません。

正しい比較方法: (1) 標準化係数(各変数を平均0・分散1に変換した上での係数)を使う、(2) 限界効果(変数を1標準偏差動かしたときのyの変化)で比較する。

また、係数の大きさが「因果関係の強さ」を意味するわけでもありません。あくまで「相関的な関連の強さ」です。
❌ 「外れ値を除外すれば正しい結果」ではない
外れ値(極端な値)を「目障りだから」「結果が綺麗にならないから」という理由で除外するのは分析の改ざんに近い行為です。

外れ値が示すもの: 本当に重要な情報(東京の超高密度、北海道の超低密度など)であることが多い。外れ値を取り除くと「日本全体の傾向」を見誤る原因になります。

正しい対処: (1) 外れ値の出現要因を調査する(なぜ東京だけ突出するのか)、(2) ノンパラメトリック手法(Spearman相関Kruskal-Wallis)を使う、(3) 外れ値を含む結果と除外した結果の両方を提示し、解釈を読者に委ねる。
❌ 「サンプルサイズが大きい=信頼できる」ではない
サンプルサイズ(n)が大きいと統計的検定の検出力は上がりますが、それは「偶然による誤差を減らす効果」にすぎません。

nが大きくても解消されない問題:
選択バイアス標本が偏っている)
測定誤差(変数の定義が曖昧)
欠損値のパターン(欠損がランダムでない)
交絡変数の見落とし

例: 1万人にWeb調査して「ネット利用と幸福度は強く相関」と言っても、そもそも回答者がネットユーザー寄りに偏っているため、母集団全体の結論にはなりません。
❌ 「複雑なモデル=より良い分析」ではない
ランダムフォレストニューラルネット・複雑な階層モデルなど、高度な手法を使えば「良い分析」と感じがちですが、必ずしもそうではありません。

過学習(overfitting)の罠: モデルが複雑すぎると、訓練データ偶然のパターンまで学習してしまい、新しいデータでは予測精度が落ちます。

シンプルさの価値: 重回帰分析相関分析は「結果が解釈しやすい」「再現性が高い」という大きな利点があります。複雑な手法はシンプルな手法で答えが出ない時の最後の手段です。
❌ 「多重共線性は気にしなくていい」ではない
多重共線性とは、説明変数同士の相関が極めて強い状態のこと。これを放置すると、回帰係数符号や大きさが入れ替わる異常事態が起こります。

典型例: 「総人口」と「労働力人口」を同時に投入すると、両者の相関が r=0.99 になり、係数推定が極端に不安定になります。「総人口は正だが、労働力人口は負」のような解釈不能な結果になりがちです。

診断と対処:
VIF(分散拡大係数)を計算し、VIF > 10 の変数を確認
相関行列で |r| > 0.8 のペアをチェック
・対処法:一方を除外、合成変数(PCA)に変換、Ridge回帰で安定化
❌ 「R²が高い=良いモデル」ではない
決定係数 R² はモデルの「当てはまりの良さ」を示しますが、 が高くてもモデルが正しいとは限りません

が高くなる罠:
説明変数を増やせば は自動的に上がる(無関係な変数を追加してもは下がらない)
時系列データでは、共通のトレンド(時間とともに増加)があるだけで が 0.9 を超える
サンプルサイズが小さいとが過大評価される

代替指標: 調整済み (変数の数でペナルティ)AICBICモデル選択基準)を併用してください。予測力の真の評価には交差検証(cross-validation)テストデータ を見ること。
❌ 「ステップワイズで選んだ変数は重要」ではない
ステップワイズ法(バックワード・フォワード選択)は便利ですが、p値ベースの変数選択は再現性に問題があると批判されています。

問題点:
同じデータでも実行順序によって最終モデルが変わる
p値を繰り返し見ることで「偶然に有意な変数」を拾ってしまう(p-hacking
係数標準誤差が過小評価され、信頼区間が嘘っぽくなる

より良い方法:
事前に変数を理論で絞る(先行研究から候補を選ぶ)
LASSO回帰(自動かつ統計的に正当化された変数選択)を使う
交差検証AIC/BIC 最小モデルを選ぶ
❌ 「線形回帰なら線形関係を前提にすべき」
重回帰分析線形関係を前提とします。実際の関係が非線形なのに線形モデルで分析すると、本当の関係を見逃します

非線形の例:
U字型関係: 失業率と物価上昇率(フィリップス曲線)
逓減効果: 所得と幸福度(年収 800万円までは強い正の効果、それ以上は飽和)
閾値効果: 高齢化率と医療費(ある水準を超えると急激に上がる)

診断と対処:
残差プロット残差が0周辺に均等に分布しているか確認
変数の対数変換・二乗項追加で非線形性を取り込む
・どうしても線形では捉えられないなら、機械学習RF・GBM)を併用する
❌ 「データに当てはまった=予測に使える」ではない
「過去のデータでフィットしたから将来も予測できる」と思うのは危険です。

過学習(overfitting)の例: 47都道府県のデータに10個の説明変数を投入すれば、ほぼ完璧にフィットします(自由度がほぼゼロ)。でもそのモデルを新しい年度に適用すると、予測精度はほぼランダム並みに落ちることがあります。

正しい予測力の評価:
・データを訓練用 70%テスト用 30%に分割し、テスト用での予測精度を見る
k分割交差検証(k-fold CV)で予測の安定性を確認
・「説明変数の数 ≪ サンプルサイズ」のバランスを意識(目安:n > 10 × 変数数)

📖 用語集(この記事に出てくる統計用語)

統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。

p値
「効果がない」と仮定したときに、観察されたデータ(またはより極端なデータ)が得られる確率。0〜1の値で、慣例的に 0.05(5%)未満を「有意」と判断する。
有意水準
「偶然」と「意味のある違い」を分ける基準。通常 α=0.05(5%)を使う。p値 < α なら「有意」と判定。
信頼区間
「真の値はこの範囲にあるだろう」という幅。95%信頼区間 = 同じ実験を100回繰り返したら95回はこの範囲に真の値が入る。
サンプルサイズ
分析に使ったデータ点の数(n)。一般にnが大きいほど推定が安定し、わずかな差も検出できるようになる。
標準誤差
推定値(係数など)のばらつきの目安。標準誤差が小さいほど推定値が安定している。
正規分布
釣鐘型の左右対称な分布。多くのパラメトリック検定(t検定F検定など)は「データが正規分布に従う」ことを仮定する。
因果相関
相関がある」と「原因と結果の関係(因果)」は別物。アイスクリームの売上と水難事故は相関するが、原因は両者とも「夏の暑さ」。
外れ値
他のデータから極端に離れた値。分析結果を歪める原因になるため、検出して除外するか別途扱う必要がある。
欠損値
データが取得できなかった部分(NaN・空白)。除外するか補完(平均代入・回帰代入など)するかが分析上の重要な判断点。
VIF
Variance Inflation Factor分散拡大係数)。多重共線性の強さを示す指標。VIF > 10 で「強い多重共線性あり」と判断。
係数回帰係数
説明変数 x が1単位増えたとき、目的変数 y が平均でどれだけ変化するか」を示す数値。正の値は正の影響、負の値は負の影響。
多重共線性
説明変数同士の相関が強すぎる状態。係数推定が不安定になり、解釈を誤る原因になる。VIF > 10 が警告サイン。
標準化係数
変数の単位の影響を取り除いた係数。複数の変数の影響の大きさを単位に依存せず比較するために使う。
決定係数 R²
回帰モデル目的変数のばらつきの何%を説明できるかを示す指標。0〜1の値で、1に近いほどモデルの説明力が高い。

📐 使っている手法をわかりやすく解説

統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。

◆ 統計の基本概念(どの論文にも共通)

🔍 p値有意確率)とは
何?
「もし本当に効果がなかったとしたら、今回の結果(またはもっと極端な結果)が偶然起きる確率」のこと。
なぜ必要?
帰無仮説(「効果なし」の仮定)のもとで検定統計量の分布から計算する。
何がわかる?
「この関係は偶然ではなく、統計的に意味がある」と主張するための客観的な根拠になる。
読み方
p < 0.05(5%未満)を「統計的に有意」と判断するのが慣例。ただし「p値が小さい=効果が大きい」ではない。効果量係数の大きさ)とセットで判断する。
🗂️ ノンパラメトリック検定とは(なぜ使うのか)
何?
「データが正規分布に従う」という仮定を置かない検定手法の総称。Kruskal-Wallis検定・Mann-Whitney U検定などが代表例。
なぜ必要?
データの値ではなく「順位」に変換して検定統計量を計算する。外れ値や偏った分布に対しても安定して機能する。
何がわかる?
サンプルサイズが小さい・データが歪んでいる・外れ値がある場合でも、グループ差の有無を検定できる。
読み方
「なぜノンパラメトリックを選ぶのか」の理由を示すには、正規性検定(Shapiro-Wilk)の結果を添えるのが望ましい。結果の解釈は対応するパラメトリック検定と同様(p < 0.05 で有意差あり)。

◆ この論文で使われている手法

📈 重回帰分析
何?
複数の説明変数(原因候補)が1つの目的変数(結果)にどれだけ影響するかを同時に推定する手法。
どう使う?
目的変数 y を複数の説明変数 x₁, x₂, … で予測する式(y = a₁x₁ + a₂x₂ + … + b)を最小二乗法でフィットさせる。
何がわかる?
複数の要因が混在するなかで「どれが一番効いているか」を一度に検証できる。交絡変数を統制できる。
結果の読み方
係数(a₁, a₂…)のプラスは正の影響、マイナスは負の影響。p < 0.05 で統計的に有意。が1に近いほどモデルの説明力が高い。
⚠️ 注意点
(1) 多重共線性を必ずVIFで確認(VIF>10で警告)。(2) 線形性の仮定—関係が曲線なら対数変換や二乗項を追加。(3) 残差プロット正規性・等分散性を確認。(4) サンプル数は最低でも「説明変数数×10」が目安。(5) 外れ値1つ係数が大きく変わるのでCook距離で確認。
🔗 相関分析
何?
2つの変数の「一緒に増減する傾向の強さと向き」を −1〜+1 の相関係数 r で数値化する手法。
どう使う?
散布図を描き、Pearson(連続データ)または Spearman(順序データ・外れ値に強い)の相関係数を計算する。
何がわかる?
「気温が高い県ほど熱中症指標が高い」などの傾向を素早く確認できる。変数選択の第一歩として使われることも多い。
結果の読み方
r > +0.7 は強い正の相関、r < −0.7 は強い負の相関、|r| < 0.3 はほぼ無相関相関因果関係を示すものではない点に注意。
⚠️ 注意点
(1) 多重共線性を必ずVIFで確認(VIF>10で警告)。(2) 線形性の仮定—関係が曲線なら対数変換や二乗項を追加。(3) 残差プロット正規性・等分散性を確認。(4) サンプル数は最低でも「説明変数数×10」が目安。(5) 外れ値1つ係数が大きく変わるのでCook距離で確認。
📊 ジニ係数ローレンツ曲線
何?
所得や医療資源などの「不平等度(格差)」を0〜1の数値で表す指標。0が完全平等、1が完全不平等。
どう使う?
データを昇順に並べ、累積シェアの曲線(ローレンツ曲線)と完全平等線との面積から計算する。
何がわかる?
「都道府県間の医師数の格差は大きいか」「格差は拡大・縮小しているか」を客観的に測れる。
結果の読み方
ジニ係数 0.3 以上は格差が大きい水準。時系列変化で格差のトレンドを読む。
⚠️ 注意点
(1) 多重共線性を必ずVIFで確認(VIF>10で警告)。(2) 線形性の仮定—関係が曲線なら対数変換や二乗項を追加。(3) 残差プロット正規性・等分散性を確認。(4) サンプル数は最低でも「説明変数数×10」が目安。(5) 外れ値1つ係数が大きく変わるのでCook距離で確認。
↔️ VAR(ベクトル自己回帰)/ Granger因果検定
何?
複数の時系列変数が互いに影響し合う関係を分析する手法(VAR)と、「AがBの予測に役立つか」を検定する手法(Granger因果)。
どう使う?
VARは全変数を互いに説明変数として同時回帰Granger因果F検定でAのラグ変数がBの予測精度を向上させるかを確認する。
何がわかる?
「女性就業率と出生率はどちらが先に動くか」「リード・ラグ関係」を特定できる。
結果の読み方
Granger因果 p < 0.05 → 「Aの過去値はBの予測に役立つ」(ただし真の因果とは限らない)。
⚠️ 注意点
(1) 多重共線性を必ずVIFで確認(VIF>10で警告)。(2) 線形性の仮定—関係が曲線なら対数変換や二乗項を追加。(3) 残差プロット正規性・等分散性を確認。(4) サンプル数は最低でも「説明変数数×10」が目安。(5) 外れ値1つ係数が大きく変わるのでCook距離で確認。

🚀 発展の可能性(結果 X → 新仮説 Y → 課題 Z)

この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。

① データ・時間的拡張
結果 X
本論文は特定の年度・地域の断面データ(または限られた時系列)で分析を行った。
新仮説 Y
より新しい年度のデータや市区町村レベルの細粒度データを使えば、知見の時間的頑健性や地域内格差を検証できる。
課題 Z
(1)統計センターから最新の SSDSE をダウンロードし、同じ分析を再実行する。(2)結果が変わった場合、その要因(コロナ・政策変化など)を考察する。(3)市区町村データ(SSDSE-A/C/F)で分析単位を細かくした場合の結果と比較する。
② 手法の発展:重回帰分析 の次のステップ
結果 X
本論文は 重回帰分析 を用いた推定を行った。
新仮説 Y
パネルデータ固定効果モデルFE)による都道府県固有の差の統制 により、本分析では統制できていない問題を解消できる可能性がある。
課題 Z
(1)パネルデータ固定効果モデルFE)による都道府県固有の差の統制 を実装し、本論文の係数推定と比較する。(2)操作変数法IV)による内生性の解消 も試し、結果の頑健性を確認する。(3)推定結果の変化から、元の分析の仮定のどれが重要だったかを考察する。
③ 政策提言・実践への応用
結果 X
本論文は分析結果から特定の変数が目的変数に影響することを示した。
新仮説 Y
分析対象を日本全国から特定地域に絞ること、または逆に国際比較に拡張することで、政策の移転可能性と文脈依存性を検証できる。
課題 Z
(1)有意な変数を「政策で変えられるもの」と「変えにくいもの」に分類する。(2)政策で変えられる変数について、係数の大きさから「どれだけ変えればどれだけ効果があるか」を試算する。(3)自治体・政策立案者への提言として、実現可能なアクションプランを1枚にまとめる。

🎯 自分でやってみよう(5つのチャレンジ)

学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。

★☆☆☆☆ 入門
CH1. 同じデータで分析を再現する
まずは付属の Python スクリプトをそのまま実行し、論文と同じ図を再現してみてください。
ポイント: 各図がどのコード行から生成されているか辿る。エラーが出たら原因を考える。
★★☆☆☆ 初級
CH2. 説明変数を1つ追加・除外して結果を比較
本論文の分析モデルから説明変数を1つ抜いて再実行、あるいは1つ追加して再実行してください。
ポイント: 係数p値 がどう変わったか観察する。多重共線性が原因で結果が変わる例を見つけられたら理想的。
★★★☆☆ 中級
CH3. 別の年度・別の都道府県で同じ分析を試す
SSDSE の別の年度(例:2015年度・2020年度)または特定都道府県のみのデータで同じ分析を実行してください。
ポイント: 時代や地域によって結論が変わるか? 変わるならその理由を考察する。
★★★★☆ 上級
CH4. 別の手法を組み合わせる
本論文の手法 + 1つの追加手法(例:重回帰 + LASSO相関分析 + 主成分分析)で結果を比較してください。
ポイント: 手法の違いで結論が変わるか? どちらが妥当かを「なぜ」とともに説明できるように。
★★★★★ 発展
CH5. オリジナルの問いを立てて分析する
本論文の手法を借りて、あなた自身の問いを立てて分析してください。 例:「カフェの数と幸福度に関連はあるか」「教育費の高い県は出生率も高いか」など。
ポイント: 問い・データ・手法・結論を1ページのレポートにまとめる。これがデータサイエンスの「実践」。
💡 ヒント: 詰まったら本サイトの他の論文(同じ手法を使っている)のスクリプトをコピーして組み合わせるのが効率的です。手法ガイド・用語集も参考に。

💼 この手法は実社会でこう使われている

本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。

🏛️
行政の政策立案
都道府県・市区町村の政策担当者は、本論文と同様のデータ分析を用いて「どこに予算を投じれば効果が出るか」を検討します。 例えば医療費削減策、移住促進策、子育て支援策などの効果予測・効果検証に直結します。
🏢
企業のマーケティング・出店戦略
小売チェーン・サービス業の出店戦略では、地域特性(人口構成、所得、ライフスタイル)と売上の関係を本論文と同じ手法で分析します。 ECサイトでも顧客セグメント分析・購買要因分析に類似手法が使われます。
🏥
医療・公衆衛生
感染症の流行予測、医療資源配分の最適化、健康格差の地域要因分析などで、本論文の統計手法は標準的に使われています。 WHO・厚労省レベルの政策評価でも同じ手法が活躍しています。
📊
メディア・ジャーナリズム
新聞・テレビの社会調査記事、選挙予測、世論調査の分析でも、本論文と同じ手法(回帰分析・クラスタリングなど)が使われています。 データジャーナリズムの記事はこの種の分析が中核です。
🎓
学術研究(隣接分野)
経済学・社会学・公衆衛生学・教育学・地理学などの実証研究では、本論文と同じ手法が日常的に使われます。 専門誌に掲載される論文の8割以上が、こうした統計手法に基づいて結論を出しています。
💰
金融・保険業界
与信判断(融資審査)、保険料の地域別設定、不動産価格予測などで、本論文と同様のモデリング手法が広く活用されています。 統計分析の能力は金融業界の必須スキルになっています。

🤔 よくある質問(読者からの想定Q&A)

この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。

Q1. この分析、自分でもできますか?
はい、できます。SSDSE データは無料で公開されており、Python の pandas, scikit-learn, statsmodels を使えば全く同じ手順で再現可能です。本ページ下部のスクリプトを実行するだけで結果が得られます。
Q2. 使われている手法は他の分野にも応用できますか?
十分応用可能です。本論文の[手法]は、医療・教育・経済・環境など他のドメインでも標準的に使われる手法です。データの中身(変数)を入れ替えるだけで、別の問いにも適用できます。
Q3. 結論は本当に「因果関係」を示していますか?
本論文は「観察データ」を使った分析であり、厳密な意味での「因果関係」を完全に証明したわけではありません。あくまで「強い関連が見られた」という事実を提示しているにとどまります。真の因果を示すには、無作為化比較試験(RCT)か、自然実験を活用したIVDiD 等の手法が必要です。
Q4. データの最新版を使うとどうなりますか?
SSDSE は毎年更新されているため、最新版を使えば近年のトレンド(特にコロナ禍以降の変化)も含めて分析できます。ただし、結論が変わる可能性もあります。それ自体が新しい発見につながります。
Q5. もっと深く学ぶには何を読めばいいですか?
「計量経済学」「データサイエンス入門」「統計的因果推論」などのテキストが入門に向いています。Python の場合は『Python ではじめる機械学習』(オライリー)、R の場合は『R で学ぶ統計学』が定番です。本サイトの他の論文も読み比べてみてください。