このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
日本では、大学進学率に著しい地域差が存在する。2022年度のデータでは、最高の京都府(73.0%)と最低の沖縄県(46.2%)の間には約27ポイントの差があり、居住地域が子どもの教育機会を大きく規定している可能性がある。
まず「都市部と地方の教育格差進学率・教育費の地域差分析」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。
本研究は、SSDSE-B(都道府県別統計データ)を用いて、教育費・所得水準・大学数などの社会経済的要因と大学進学率の関係を定量的に分析し、都市部と地方の教育格差の構造を明らかにすることを目的とする。
SSDSE-B 相関分析 OLS回帰 地域別比較 時系列分析
統計数理研究所が提供する「社会・人口統計体系データセット(SSDSE-B-2026)」を使用する。このデータセットは47都道府県の社会・人口・経済統計を2012〜2023年度にわたって収録したパネルデータである。
| 項目 | 内容 |
|---|---|
| データ | SSDSE-B-2026.csv(社会・人口統計体系, 都道府県別) |
| 対象 | 全47都道府県 |
| 期間 | 2012〜2023年度(12年間) |
| 横断分析年 | 2022年度(直近の完全データ年) |
| 観測数 | N=47(横断)/ N=564(パネル全体) |
| 変数名 | 定義 | 出典変数(SSDSE-B) | 想定効果 |
|---|---|---|---|
| 大学進学率(%) 目的変数 | 高校卒業者のうち進学者数 / 高校卒業者数 × 100 | 高等学校卒業者のうち進学者数 / 高等学校卒業者数 | — |
| 教育費_万円 | 二人以上世帯の教育費支出(万円/月) | 教育費(二人以上の世帯)÷ 10,000 | 正(教育投資→進学) |
| 高齢化率(%) | 65歳以上人口 / 総人口 × 100 | 65歳以上人口 / 総人口 | 負(高齢化→地方→低進学) |
| 大学数 | 都道府県内の大学数 | 大学数 | 正(アクセス性→進学) |
| 消費支出_log | 二人以上世帯の消費支出(対数変換) | log(消費支出(二人以上の世帯)) | 正(所得代理→進学) |
| 師弟比_中学 | 中学校生徒数 / 中学校教員数 | 中学校生徒数 / 中学校教員数 | 負(過大クラス→教育質低下) |
2012年から2023年にかけて、全47都道府県の大学進学率がどのように推移してきたかを地域ブロック別の平均値で可視化する。
| 地域ブロック | 2022年 平均進学率(%) | 全国平均との差 | 傾向 |
|---|---|---|---|
| 近畿 | 63.5 | +6.9pp | 一貫して高位 |
| 関東 | 62.5 | +5.9pp | 高位・安定 |
| 中部 | 58.7 | +2.1pp | 全国平均上 |
| 中国・四国 | 55.6 | −1.0pp | 全国平均並み |
| 北海道・東北 | 50.6 | −6.0pp | 全国平均以下 |
| 九州・沖縄 | 49.6 | −7.0pp | 最も低位 |
地域格差を「どのくらい差がある状態か」を数値で表すには、変動係数(Coefficient of Variation:CV)が有効。CVは標準偏差を平均で割ることで、単位に依存しない相対的なばらつきを表す。
CVが大きいほど「平均に対してばらつきが大きい」=格差が大きい状態。教育研究では教育格差の時系列変化をCVで追跡することが多い。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import numpy as np import pandas as pd import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from scipy import stats import statsmodels.api as sm import warnings warnings.filterwarnings('ignore') 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} のように書式も指定できます。24 25 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 | # 変数生成 df_b['大学進学率'] = df_b['高等学校卒業者のうち進学者数'] / df_b['高等学校卒業者数'].replace(0, np.nan) * 100 df_b['教育費_万円'] = df_b['教育費(二人以上の世帯)'] / 10000 df_b['高齢化率'] = df_b['65歳以上人口'] / df_b['総人口'] * 100 df_b['消費支出_log'] = np.log(df_b['消費支出(二人以上の世帯)'].clip(lower=1)) df_b['師弟比_中学'] = df_b['中学校生徒数'] / df_b['中学校教員数'].replace(0, np.nan) 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) ax.axhline(df_b[df_b['年度'] == 2022]['大学進学率'].mean(), color='red', linestyle=':', alpha=0.5, linewidth=1) plt.tight_layout() plt.savefig(os.path.join(FIG_DIR, '2022_H4_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(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。消費支出(所得の代理変数)と大学進学率の関係を2022年の47都道府県データで可視化し、相関係数と単回帰直線を算出する。
| 地域 | 消費支出水準 | 進学率水準 | パターン |
|---|---|---|---|
| 関東(東京都・神奈川県等) | 高 | 高 | 高所得・高進学 |
| 近畿(京都府・大阪府等) | 中〜高 | 高 | 大学集積効果あり |
| 中部(愛知県等) | 中 | 中〜高 | 製造業中心で中程度 |
| 北海道・東北 | 低〜中 | 低 | 所得・進学ともに低位 |
| 九州・沖縄 | 低 | 最低 | 構造的格差 |
r = 0.44 の正の相関は「消費支出が高い都道府県ほど進学率が高い」という事実を示すが、これは因果関係(causal relationship)ではない点に注意が必要。
交絡因子の可能性: 都市部であること(大学が近い・情報が多い・文化的資本が高い)が消費支出と進学率の両方を引き上げている「第三の変数」かもしれない。このような変数を交絡因子(confounder)という。
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | df_2022 = df_b[df_b['年度'] == 2022].copy() df_sc = df_2022[['都道府県', '消費支出_log', '大学進学率', '地域']].dropna() fig, ax = plt.subplots(figsize=(9, 6)) for reg, grp in df_sc.groupby('地域'): ax.scatter(grp['消費支出_log'], grp['大学進学率'], color=region_colors.get(reg, 'gray'), label=reg, s=65, alpha=0.8) for _, row in df_sc.iterrows(): ax.annotate(row['都道府県'][:2], (row['消費支出_log'], row['大学進学率']), fontsize=7, alpha=0.7, xytext=(3, 3), textcoords='offset points') slope, intercept, r, p, _ = stats.linregress(df_sc['消費支出_log'], df_sc['大学進学率']) xr = np.linspace(df_sc['消費支出_log'].min(), df_sc['消費支出_log'].max(), 100) ax.plot(xr, slope * xr + intercept, 'k--', linewidth=1.5, label=f'回帰直線 (r={r:.2f}, p={p:.3f})') ax.set_xlabel('消費支出(log)', 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_H4_fig2_scatter.png'), dpi=150, bbox_inches='tight') plt.close() print("Fig2 saved") |
Fig2 saved
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() でメモリ解放。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。複数の社会経済変数を同時に投入したOLS重回帰分析により、大学進学率の決定要因を多変量で検討する。2022年度の47都道府県横断データを使用。
| 変数 | 偏回帰係数 | 標準誤差 | p値 | 判定 | 解釈 |
|---|---|---|---|---|---|
| 大学数 | +0.094 | 0.044 | 0.038 | ★ p<0.05 | 大学1校増加で進学率+0.09pp |
| 師弟比_中学 | +1.386 | 0.996 | 0.172 | n.s. | 有意でない |
| 消費支出_log | +9.375 | 15.807 | 0.556 | n.s. | 単相関は有意だが多変量では消える |
| 教育費_万円 | +1.379 | 2.550 | 0.592 | n.s. | 有意でない |
| 高齢化率 | −0.139 | 0.452 | 0.760 | n.s. | 有意でない |
| R² = 0.504 / 調整済みR² = 0.443 / F(5, 41) = 8.32, p < 0.001 | |||||
OLS重回帰の偏回帰係数 β は「他の変数を一定に保ったときの、その変数1単位変化に伴う目的変数の変化量」を示す。単回帰との違いを理解することが重要。
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | xvars = ['教育費_万円', '高齢化率', '大学数', '消費支出_log', '師弟比_中学'] df_reg = df_2022[['大学進学率'] + xvars].dropna() X = sm.add_constant(df_reg[xvars]) res = sm.OLS(df_reg['大学進学率'], X).fit() print(res.summary()) coefs = res.params.drop('const') ses = res.bse.drop('const') pvals = res.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('OLS回帰係数', fontsize=12) ax.set_title(f'大学進学率の決定要因(OLS, N=47)\nR²={res.rsquared:.3f}(赤=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_H4_fig3_ols.png'), dpi=150, bbox_inches='tight') plt.close() print("Fig3 saved") |
OLS Regression Results
==============================================================================
Dep. Variable: 大学進学率 R-squared: 0.504
Model: OLS Adj. R-squared: 0.443
Method: Least Squares F-statistic: 8.316
Date: Mon, 18 May 2026 Prob (F-statistic): 1.70e-05
Time: 11:24:03 Log-Likelihood: -141.23
No. Observations: 47 AIC: 294.5
Df Residuals: 41 BIC: 305.6
Df Model: 5
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const -76.6742 190.729 -0.402 0.690 -461.859 308.511
教育費_万円 1.3786 2.550 0.541 0.592 -3.772 6.529
高齢化率 -0.1391 0.452 -0.308 0.760 -1.052 0.774
大学数 0.0937 0.044 2.149 0.038 0.006 0.182
消費支出_log 9.3749 15.807 0.593 0.556 -22.548 41.298
師弟比_中学 1.3862 0.996 1.391 0.172 -0.626 3.399
==============================================================================
Omnibus: 1.833 Durbin-Watson: 1.951
Prob(Omnibus): 0.400 Jarque-Bera (JB): 1.592
Skew: 0.443 Prob(JB): 0.451
Kurtosis: 2.828 Cond. No. 1.03e+04
==============================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 1.03e+04. This might indicate that there are
strong multicollinearity or other numerical problems.
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()。地域ブロック別の平均大学進学率と、各ブロック内のばらつき(変動係数 CV)を並べて可視化することで、「地域間格差」(ブロック間の平均の差)と「地域内格差」(ブロック内の都道府県間の差)を同時に把握する。
| 地域ブロック | 平均進学率(%) | 標準偏差(pp) | 変動係数 CV(%) | 特徴 |
|---|---|---|---|---|
| 近畿 | 63.5 | 6.36 | 10.0 | 高進学・地域内格差も大 |
| 関東 | 62.5 | 6.39 | 10.2 | 高進学・地域内格差も大(東京 vs 茨城等) |
| 中部 | 58.7 | 3.62 | 6.2 | 進学率中程度・地域内均質 |
| 中国・四国 | 55.6 | 5.33 | 9.6 | 平均以下・地域内格差あり |
| 北海道・東北 | 50.6 | 2.93 | 5.8 | 低進学・地域内は均質(全体的に低い) |
| 九州・沖縄 | 49.6 | 4.02 | 8.1 | 最低位・地域内にもばらつき |
CV分析の結果から、都市部と地方では異なる政策が必要であることが示唆される。統計的証拠を政策立案に活かす「証拠に基づく政策立案(EBPM)」の考え方は、データサイエンスの重要な応用領域。
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | cv_by_region = df_2022.groupby('地域')['大学進学率'].agg(['mean', 'std']).dropna() cv_by_region['CV'] = cv_by_region['std'] / cv_by_region['mean'] * 100 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5)) # 地域別平均 colors_list = [region_colors.get(r, 'gray') for r in cv_by_region.index] ax1.barh(cv_by_region.index, cv_by_region['mean'], color=colors_list, alpha=0.8) ax1.set_xlabel('平均大学進学率(%)', fontsize=11) ax1.set_title('地域別 平均大学進学率(2022年)', fontsize=12, fontweight='bold') ax1.grid(axis='x', alpha=0.3) ax1.axvline(df_2022['大学進学率'].mean(), color='red', linestyle='--', linewidth=1.5, label=f'全国平均: {df_2022["大学進学率"].mean():.1f}%') ax1.legend(fontsize=9) # 変動係数 ax2.barh(cv_by_region.index, cv_by_region['CV'], color=colors_list, alpha=0.8) ax2.set_xlabel('変動係数(CV, %)', fontsize=11) ax2.set_title('地域内格差(変動係数 CV)\n(大きいほど地域内格差が大きい)', fontsize=12, fontweight='bold') ax2.grid(axis='x', alpha=0.3) plt.suptitle('地域別 大学進学率の格差分析(2022年)', fontsize=13, fontweight='bold', y=1.02) plt.tight_layout() plt.savefig(os.path.join(FIG_DIR, '2022_H4_fig4_gap.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(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。| データ・資料 | 内容 | 出典 |
|---|---|---|
| SSDSE-B-2026.csv | 都道府県別社会・人口統計(2012〜2023年) | 統計数理研究所 SSDSE |
| 高等学校卒業者のうち進学者数 | 大学進学率の分子 | 文部科学省 学校基本調査 |
| 消費支出(二人以上の世帯) | 所得水準の代理変数 | 総務省 家計調査 |
| 65歳以上人口・総人口 | 高齢化率の算出 | 総務省 住民基本台帳人口移動報告 |
| 中学校教員数・生徒数 | 師弟比(教育資源指標) | 文部科学省 学校基本調査 |
本コードはSSDSE-B-2026.csvの実データのみを使用。np.random等の合成データは一切使用していない。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。