このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
日本の地域間賃金格差は長年の政策課題となっている。本研究は「なぜ地域によって賃金水準(生活水準)が異なるのか」という問いに対し、都道府県別パネルデータを用いた固定効果回帰モデルで統計的に迫った。
まず「地域別賃金水準の決定要因消費支出・雇用指標を用いたパネル分析」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。
賃金水準の直接データとして最低賃金・平均賃金データが理想的だが、SSDSE-B のような統合公開データセットには含まれない。そこで本研究では 消費支出(二人以上の世帯)を賃金・生活水準の代理変数として使用する。消費支出は可処分所得(≒賃金)と強く連動するという経済学的根拠(ケインズの消費関数)がある。
SSDSE-B パネルOLS 固定効果モデル 代理変数 地域比較
| 項目 | 内容 |
|---|---|
| データソース | SSDSE-B-2026(社会・人口統計体系 都道府県データ) |
| 対象 | 全47都道府県 |
| 期間 | 2012〜2023年(12年間) |
| 観測数 | 47 × 12 = 564 |
| パネル構造 | バランスドパネル(欠損なし) |
まず、目的変数である消費支出(賃金代理)が6地域でどのように推移してきたかを確認する。地域間の水準差と、コロナ禍(2020〜2021年)の影響も観察できる。
分析したい概念(賃金水準)を直接測定できないとき、理論的に強く相関する別の変数(消費支出)で代替することを「代理変数の利用」という。有効な代理変数の条件は2つ:(1) 目的概念と高い相関を持つ、(2) 代理変数自体が独立した意味を持つ誤差源を持たない。
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 numpy as np import pandas as pd import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import warnings warnings.filterwarnings('ignore') from linearmodels.panel import PanelOLS 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 import os FIG_DIR = 'html/figures' DATA_B = 'data/raw/SSDSE-B-2026.csv' os.makedirs(FIG_DIR, exist_ok=True) 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) df_b = df_b.sort_values(['都道府県', '年度']).reset_index(drop=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)。pd.read_csv(...) でCSVを読み込みます。encoding='cp932' は日本語Windows由来の文字コード、header=1 は「2行目を列名として使う」。df['地域コード'].str.match(r'^R\d{5}', ...) — 正規表現で「R+数字5桁」の行(47都道府県)だけTrueにし、真偽値で行をフィルタ。.astype(int) — 列を整数に変換(年度などを数値比較するため)。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。f"...{x}..." はf-string。文字列の中に {変数} と書くだけで埋め込めて、{x:.2f} のように書式も指定できます。26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | # 変数生成 df_b['消費支出_万円'] = df_b['消費支出(二人以上の世帯)'] / 10000 df_b['消費支出_log'] = np.log(df_b['消費支出(二人以上の世帯)'].clip(lower=1)) df_b['求人倍率'] = df_b['月間有効求人数(一般)'] / df_b['月間有効求職者数(一般)'].replace(0, np.nan) df_b['高齢化率'] = df_b['65歳以上人口'] / df_b['総人口'] * 100 df_b['大学学生_log'] = np.log(df_b['大学学生数'].clip(lower=1)) df_b['純移動率'] = (df_b['転入者数(日本人移動者)'] - df_b['転出者数(日本人移動者)']) / df_b['総人口'] * 1000 region_map = { '北海道': '北海道・東北', '青森県': '北海道・東北', '岩手県': '北海道・東北', '宮城県': '北海道・東北', '秋田県': '北海道・東北', '山形県': '北海道・東北', '福島県': '北海道・東北', '茨城県': '関東', '栃木県': '関東', '群馬県': '関東', '埼玉県': '関東', '千葉県': '関東', '東京都': '関東', '神奈川県': '関東', '新潟県': '中部', '富山県': '中部', '石川県': '中部', '福井県': '中部', '山梨県': '中部', '長野県': '中部', '岐阜県': '中部', '静岡県': '中部', '愛知県': '中部', '三重県': '近畿', '滋賀県': '近畿', '京都府': '近畿', '大阪府': '近畿', '兵庫県': '近畿', '奈良県': '近畿', '和歌山県': '近畿', '鳥取県': '中国・四国', '島根県': '中国・四国', '岡山県': '中国・四国', '広島県': '中国・四国', '山口県': '中国・四国', '徳島県': '中国・四国', '香川県': '中国・四国', '愛媛県': '中国・四国', '高知県': '中国・四国', '福岡県': '九州・沖縄', '佐賀県': '九州・沖縄', '長崎県': '九州・沖縄', '熊本県': '九州・沖縄', '大分県': '九州・沖縄', '宮崎県': '九州・沖縄', '鹿児島県': '九州・沖縄', '沖縄県': '九州・沖縄', } df_b['地域'] = df_b['都道府県'].map(region_map) region_colors = { '北海道・東北': '#4e9af1', '関東': '#e05c5c', '中部': '#f0a500', '近畿': '#5cb85c', '中国・四国': '#9b59b6', '九州・沖縄': '#f39c12', } fig, ax = plt.subplots(figsize=(10, 5)) yearly = df_b.groupby(['年度', '地域'])['消費支出_万円'].mean().reset_index() for reg, grp in yearly.groupby('地域'): ax.plot(grp['年度'], grp['消費支出_万円'], marker='o', markersize=4, label=reg, color=region_colors.get(reg, 'gray')) ax.set_xlabel('年度', fontsize=12) ax.set_ylabel('消費支出(万円/月)', fontsize=12) ax.set_title('地域別 消費支出(賃金代理)の推移(2012〜2023年)', fontsize=14, fontweight='bold') ax.legend(fontsize=9) ax.grid(alpha=0.3) plt.tight_layout() plt.savefig(os.path.join(FIG_DIR, '2022_U5_14_fig1_ts.png'), dpi=150, bbox_inches='tight') plt.close() print("Fig1 saved") |
Fig1 saved
df.groupby('列').apply(関数) — グループごとに関数を適用。時系列や地域別の集計でよく使います。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。賃金水準の主要な説明変数として採用した「求人倍率」が、地域によってどのように分布しているかを確認する。求人倍率は労働市場の需給バランスを示す最も基本的な雇用指標である。
有効求人倍率は公共職業安定所(ハローワーク)に登録された求人・求職のデータから算出される。1.0を境に「求人超過(売り手市場)」か「求職超過(買い手市場)」かが決まる。ただし、ハローワーク経由でない民間求人・求職は含まれないため、実態より低めに出る傾向がある。
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | df_box = df_b[['都道府県', '地域', '求人倍率']].dropna() region_order = ['北海道・東北', '関東', '中部', '近畿', '中国・四国', '九州・沖縄'] fig, ax = plt.subplots(figsize=(10, 5)) bxdata = [df_box[df_box['地域'] == reg]['求人倍率'].values for reg in region_order] bp = ax.boxplot(bxdata, patch_artist=True, labels=region_order) for patch, reg in zip(bp['boxes'], region_order): patch.set_facecolor(region_colors.get(reg, 'gray')) patch.set_alpha(0.7) ax.set_xlabel('地域', fontsize=12) ax.set_ylabel('求人倍率', fontsize=12) ax.set_title('地域別 求人倍率の分布(2012〜2023年)', fontsize=13, fontweight='bold') ax.grid(axis='y', alpha=0.3) ax.axhline(1.0, color='red', linestyle='--', linewidth=1.5, label='倍率=1.0') ax.legend(fontsize=10) plt.tight_layout() plt.savefig(os.path.join(FIG_DIR, '2022_U5_14_fig2_boxplot.png'), dpi=150, bbox_inches='tight') plt.close() print("Fig2 saved") |
Fig2 saved
fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。固定効果モデル(PanelOLS, entity_effects=True)を推定し、各説明変数が消費支出(賃金代理)に与える影響を定量化する。都道府県固定効果により「東京は消費が高い」といった地域固有の水準差は除去され、各都道府県内での年次変動が係数を識別する。
| 説明変数 | 係数 | 標準誤差 | t統計量 | p値 | 解釈 |
|---|---|---|---|---|---|
| 求人倍率 | 0.013 | 0.014 | 0.93 | 0.352 | 非有意 |
| 高齢化率(%) | −0.001 | 0.002 | −0.28 | 0.777 | 非有意 |
| 大学学生数(log) | −0.172 | 0.080 | −2.15 | 0.032 | 有意(負) |
| 純移動率(‰) | 0.002 | 0.004 | 0.37 | 0.713 | 非有意 |
クラスター標準誤差(都道府県クラスター)による推定。F検定(固定効果の同時有意性): p<0.0001(固定効果の必要性が強く支持)。
今回の固定効果モデルでは、求人倍率・高齢化率・純移動率は非有意。これは「これらの変数が重要でない」のではなく、固定効果(都道府県の恒常的差異)を除去した後のwithin変動では有意差が検出されなかったことを意味する。つまり、「東京は求人が多くて消費も高い」という関係はwithinでなくbetween(都道府県間)に存在している可能性が高い。
大学学生数が有意な負の係数となったのは、学生が増加すると若年低所得者が増え、世帯平均消費支出を押し下げるという構成効果の可能性がある。
固定効果(entity effects)とは「各都道府県が時代を通じて持つ固有の特性(地理・産業構造・文化等)」を丸ごとコントロールする手法。固定効果を入れることで、観察できない変数による omitted variable bias(脱落変数バイアス)を防げる。
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | panel_vars = ['求人倍率', '高齢化率', '大学学生_log', '純移動率'] df_panel = df_b[['年度', '都道府県', '消費支出_log'] + panel_vars].dropna() df_panel = df_panel.set_index(['都道府県', '年度']) y = df_panel['消費支出_log'] X = sm.add_constant(df_panel[panel_vars]) try: mod = PanelOLS(y, X, entity_effects=True, drop_absorbed=True) res = mod.fit(cov_type='clustered', cluster_entity=True) coefs = res.params.drop('const', errors='ignore') ses = res.std_errors.drop('const', errors='ignore') pvals = res.pvalues.drop('const', errors='ignore') print(res.summary) except Exception as e: print(f"FE error: {e}") df_ols = df_b[df_b['年度'] == 2022][['消費支出_log'] + panel_vars].dropna() res_ols = sm.OLS(df_ols['消費支出_log'], sm.add_constant(df_ols[panel_vars])).fit() coefs = res_ols.params.drop('const') ses = res_ols.bse.drop('const') pvals = res_ols.pvalues.drop('const') fig, ax = plt.subplots(figsize=(8, 5)) colors_c = ['#e05c5c' if p < 0.05 else '#888888' for p in pvals] ax.barh(range(len(coefs)), coefs, xerr=1.96 * ses, color=colors_c, alpha=0.8, error_kw={'elinewidth': 1.5, 'capsize': 4}) ax.set_yticks(range(len(coefs))) ax.set_yticklabels(coefs.index, fontsize=10) ax.axvline(0, color='black', linewidth=0.8) ax.set_xlabel('回帰係数', fontsize=12) ax.set_title('消費支出(賃金代理)の決定要因 — FEパネルOLS\n(赤=p<0.05, 灰=非有意)', fontsize=12, fontweight='bold') ax.grid(axis='x', alpha=0.3) plt.tight_layout() plt.savefig(os.path.join(FIG_DIR, '2022_U5_14_fig3_fe_coef.png'), dpi=150, bbox_inches='tight') plt.close() print("Fig3 saved") |
PanelOLS Estimation Summary
================================================================================
Dep. Variable: 消費支出_log R-squared: 0.0133
Estimator: PanelOLS R-squared (Between): -8.2631
No. Observations: 564 R-squared (Within): 0.0133
Date: Mon, May 18 2026 R-squared (Overall): -5.7373
Time: 11:24:20 Log-likelihood 937.87
Cov. Estimator: Clustered
F-statistic: 1.7303
Entities: 47 P-value 0.1419
Avg Obs: 12.000 Distribution: F(4,513)
Min Obs: 12.000
Max Obs: 12.000 F-statistic (robust): 1.4784
P-value 0.2074
Time periods: 12 Distribution: F(4,513)
Avg Obs: 47.000
Min Obs: 47.000
Max Obs: 47.000
Parameter Estimates
==============================================================================
Parameter Std. Err. T-stat P-value Lower CI Upper CI
------------------------------------------------------------------------------
const 14.324 0.8108 17.666 0.0000 12.731 15.917
求人倍率 0.0131 0.0140 0.9312 0.3522 -0.0145 0.0406
高齢化率 -0.0007 0.0023 -0.2839 0.7766 -0.0052 0.0038
大学学生_log -0.1724 0.0803 -2.1468 0.0323 -0.3302 -0.0146
純移動率 0.0015 0.0040 0.3677 0.7133 -0.0063 0.0092
==============================================================================
F-test for Poolability: 20.300
P-value: 0.0000
Distribution: F(46,513)
Included effects: Entity
Fig3 savedfig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。sm.add_constant(X) — 切片項(定数1の列)を先頭に追加。statsmodelsで必須。sm.OLS(y, X).fit() — 最小二乗法でモデルを推定。model.params, model.pvalues, model.conf_int() で結果取得。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。パネル分析(within推定)に対して、2022年の断面データで求人倍率と消費支出の関係を直感的に確認する。断面での相関はbetween(都道府県間)の差を示すため、固定効果モデルの結果と異なる情報を与える。
ケインズ(1936)の提唱した消費関数 C = α + βY は、消費C が所得Y の線形関数であるという理論。β は限界消費性向(MPC)と呼ばれ、所得が1単位増えたとき消費がどれだけ増えるかを示す(通常0.6〜0.8)。この理論的関係が代理変数利用の経済学的根拠となる。
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | df_2022 = df_b[df_b['年度'] == 2022].copy() df_sc = df_2022[['都道府県', '求人倍率', '消費支出_万円', '地域']].dropna() fig, ax = plt.subplots(figsize=(9, 6)) for reg, grp in df_sc.groupby('地域'): ax.scatter(grp['求人倍率'], grp['消費支出_万円'], color=region_colors.get(reg, 'gray'), label=reg, s=60, alpha=0.8) for _, row in df_sc.iterrows(): ax.annotate(row['都道府県'][:2], (row['求人倍率'], row['消費支出_万円']), fontsize=6, alpha=0.6, xytext=(2, 2), textcoords='offset points') slope, intercept, r, p, _ = stats.linregress(df_sc['求人倍率'], df_sc['消費支出_万円']) xr = np.linspace(df_sc['求人倍率'].min(), df_sc['求人倍率'].max(), 100) ax.plot(xr, slope * xr + intercept, 'k--', linewidth=1.5, label=f'回帰直線 (r={r:.2f}, p={p:.3f})') ax.set_xlabel('求人倍率', fontsize=12) ax.set_ylabel('消費支出(万円/月)', fontsize=12) ax.set_title('求人倍率 vs 消費支出(2022年, N=47)', fontsize=13, fontweight='bold') ax.legend(fontsize=8, ncol=2) ax.grid(alpha=0.3) plt.tight_layout() plt.savefig(os.path.join(FIG_DIR, '2022_U5_14_fig4_scatter.png'), dpi=150, bbox_inches='tight') plt.close() print("Fig4 saved") print("All done!") |
Fig4 saved All done!
df.groupby('列').apply(関数) — グループごとに関数を適用。時系列や地域別の集計でよく使います。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。stats.linregress(x, y) — 単回帰の傾き・切片・r値・p値・標準誤差を返します。使わない値は _ で受け取り。for _, row in df.iterrows() — DataFrameを1行ずつ取り出すループ。1点ずつ描画したいときに使用。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。47都道府県 × 12年のバランスドパネルデータを用いた固定効果OLS推定の結果:
| 項目 | 内容・出典 |
|---|---|
| SSDSE-B-2026.csv | 統計数理研究所「社会・人口統計体系データセット」都道府県データ(2012〜2023年) |
| linearmodels | PanelOLS: pip install linearmodels |
| statsmodels | OLS, add_constant: pip install statsmodels |
| scipy | stats.linregress: pip install scipy |
本教育用コードはSSDSE-B-2026.csv(実公開データ)のみを使用。合成データ・乱数生成は一切使用していない。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。