この教材は原論文と同じデータを読み込み、同じ手順で計算し直しています。画面に出る数値と図は、あなたのブラウザがその場で計算した結果です。
| 原論文が使ったデータ | SSDSE-B・e-Stat 分析単位:都道府県 中核手法:パネルデータ分析・重回帰分析・固定効果モデル・ランダム効果モデル・相関分析 |
|---|---|
| この教材が使うデータ |
|
| 原論文(PDF) | 我が国における人口増減の決定要因 優秀賞/竹内 太郎(大阪大学医学部) |
▶ ここに書いてある分析は、ページ下部の「🐍 ブラウザで動かす」でそのまま実行できます(インストール不要)。動かしているのは code/2019_U2_yushu.py(230 行)そのものです。
このページの実データ追試を自分で動かすには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
※ 原論文は SSDSE-2019B と e-Stat の 2005〜2016年度データを使いました。現在配布中の SSDSE-B-2026 の収録期間は 2012〜2023年度で、医師数・歯科医師数・看護師数・精神科病院数や年齢階級別人口(3-5歳など)は収録されていません。そのため本ページでは、図1・図3・図4を実データによる追試(期間・変数定義が異なる)、図2(原論文 表2 の解析結果)を原論文の報告値の可視化(再計算ではない)として扱います(詳細は「データと変数」の再現範囲を参照)。
日本における人口減少は社会的な問題である。原論文の引用する推計によれば、2010年の国勢調査で1億2806万人であった我が国の総人口は、2060年には8674万人に減少すると推計されている。また、老年人口割合(65歳以上人口)は増加し続けており、2060年にはおよそ40%に達すると推計されている(いずれも厚生労働白書からの引用)。
人口減少は次の3段階に分けて捉えることができる:
| 段階 | 特徴 |
|---|---|
| 第1段階 | 若年人口は減少するが、高齢者は増加する時期(日本は今ここ) |
| 第2段階 | 若年人口の減少が加速するとともに、高齢者人口が微減へと転じる時期 |
| 第3段階 | 若年人口の減少がより一層加速化し、高齢者人口も減少する時期 |
人口減少がもたらす影響は、経済(就業者数の減少と経済成長の停滞)、地域社会(労働人口減少や消費の停滞)、社会保障(担い手である生産年齢人口の減少による社会保障・財政維持の困難)と広範にわたる。
これまでも、医療・教育・労働・財政基盤といった各分野の諸要因が人口増減に与える影響は分析されてきた。しかし多くは単年度のデータを用いた解析だった。社会的要因は時間の経過に従って変化する。ならば、複数年度のデータをまとめて経時的変化も考慮した解析を行えば、人口増減に影響を与える要因をより適切に検討できるはずだ——これが本研究の出発点である。
パネルデータ分析 固定効果モデル ランダム効果モデル ハウスマン検定 Breusch-PaganのLM検定
被説明変数・説明変数とも、SSDSE-2019B(独立行政法人統計センターの教育用標準データセット・都道府県/時系列データ)と政府統計の総合窓口(e-Stat)から取得した、2005〜2016年度・47都道府県のデータである。統計解析は Stata/MP 15.0、仮説検定は有意水準5%で行われた。
人口増減率は自然増減率と社会増減率の和として、SSDSE-2019B の出生数・死亡数・転入者数・転出者数・日本人人口から算出された(人口千対)。
教育、健康・医療の2分野から15指標を選び、高齢化の影響を調整するため老年人口割合も説明変数に含めた。学校数は対象年齢人口10万人あたり、医療関係は人口10万人あたりに標準化されている。
| 分野 | 項目名 | コード | 出典データ |
|---|---|---|---|
| 人口・世帯 | 老年人口割合(65歳以上人口割合) | A03503 | 国勢調査、人口推計 |
| 教育 | 幼稚園数(3-5歳人口10万人あたり) | E0110104 | 学校基本調査 |
| 小学校数(6-11歳人口10万人あたり) | E0110101 | ||
| 中学校数(12-14歳人口10万人あたり) | E0110102 | ||
| 高等学校数(15-17歳人口10万人あたり) | E0110103 | ||
| 大学数(人口10万人あたり) | E0610102 | ||
| 中学校卒業者進学率 | E09401 | ||
| 高等学校卒業者進学率 | E09402 | ||
| 健康・医療 | 一般病院数(人口10万人あたり) | I0910103 | 医療施設動態調査 |
| 一般診療所数(人口10万人あたり) | I0910105 | ||
| 歯科診療所数(人口10万人あたり) | I0910106 | ||
| 精神科病院数(人口10万人あたり) | I0910107 | ||
| 医療施設に従事する医師数(人口10万人あたり) | I0920101 | 医師・歯科医師・薬剤師調査 | |
| 医療施設に従事する歯科医師数(人口10万人あたり) | I0920201 | ||
| 医療施設に従事する看護師・准看護師数(人口10万人あたり) | I0920301 |
※ コードは原論文 表1 の社会生活統計指標コードの転記(先頭の英字は指標分類)。
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 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') — グラフを画面表示せずファイルに保存するためのおまじない。statsmodels — 回帰分析・パネルデータ分析用のライブラリ。原論文は Stata/MP 15.0 を使いましたが、同型のモデルは Python でも推定できます。plt.rcParams['font.family'] — グラフの日本語表示用フォント指定(Macは Hiragino Sans、Windowsなら Yu Gothic 等)。38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | # ===== ステップ1: SSDSE-B-2026 の読み込みと人口増減率の計算 ===== df = pd.read_csv(DATA_B, encoding='cp932', header=1) df = df[df['地域コード'].str.match(r'^R\d{5}', na=False)].copy() df['年度'] = df['年度'].astype(int) # 人口増減率 = 自然増減率 + 社会増減率(原論文 3節の定義そのまま) # 自然増減率 = (出生数 - 死亡数) / 日本人人口 * 1000 # 社会増減率 = (転入者数 - 転出者数) / 日本人人口 * 1000 df['自然増減率'] = (df['出生数'] - df['死亡数']) / df['日本人人口'] * 1000 df['社会増減率'] = (df['転入者数(日本人移動者)'] - df['転出者数(日本人移動者)']) / df['日本人人口'] * 1000 df['人口増減率'] = df['自然増減率'] + df['社会増減率'] # 説明変数(SSDSE-B-2026 で計算可能な11指標。医師数などは未収録) df['老年人口割合'] = df['65歳以上人口'] / df['総人口'] * 100 for col in ['幼稚園数', '小学校数', '中学校数', '高等学校数', '大学数', '一般病院数', '一般診療所数', '歯科診療所数']: df[col + '_10万対'] = df[col] / df['総人口'] * 100000 # 人口10万人あたり df['中学校卒業者進学率'] = df['中学校卒業者のうち進学者数'] / df['中学校卒業者数'] * 100 df['高等学校卒業者進学率'] = df['高等学校卒業者のうち進学者数'] / df['高等学校卒業者数'] * 100 print(f"【SSDSE-B-2026】47都道府県 × {df['年度'].nunique()}年度" f"({df['年度'].min()}〜{df['年度'].max()})= {len(df)}観測") print(' ※ 原論文の SSDSE-2019B(2005〜2016年度)とは収録期間が異なる') |
【SSDSE-B-2026】47都道府県 × 12年度(2012〜2023)= 564観測 ※ 原論文の SSDSE-2019B(2005〜2016年度)とは収録期間が異なる
pd.read_csv(..., encoding='cp932', header=1) — SSDSE-B は1行目が変数コード、2行目が日本語の変数名なので、2行目を列名にします。str.match(r'^R\d{5}') — 地域コードが「R+数字5桁」の行=47都道府県だけを残します(全国計の行を除外)。* 1000 で「人口千人あたり(人口千対)」になります。/ 総人口 * 100000 で「人口10万人あたり」に変換。原論文は幼稚園〜高等学校を対象年齢人口(3-5歳など)10万人あたりで定義していますが、SSDSE-B-2026 には年齢階級別人口(3-5歳など)がないため総人口で代用しています(追試の限界)。lambda や列名のループを使うと、同じ変換を複数の列にまとめて適用できます。コピペの繰り返しはミスのもと。回帰分析に入る前に、原論文はまず15指標それぞれの経年変化(全国平均値の推移及び標準偏差)を図1-(a)〜(o) で確認している。12年間(2005〜2016年度)の全国的な傾向は次の通りである(原論文 4節)。
| 傾向 | 指標 |
|---|---|
| 概ね増加傾向 | 老年人口割合、人口10万人あたりの大学数・一般診療所数・歯科診療所数・医師数・歯科医師数・看護師/准看護師数 |
| 2009年度頃を境に減少傾向へ | 人口10万人あたりの幼稚園数・小学校数・中学校数・高等学校数 |
| 12年間ほぼ一貫して減少 | 人口10万人あたりの一般病院数 |
※ 原論文 図1-(a)〜(o) は15枚の経年変化図。本ページでは SSDSE-B-2026 で計算できる4指標のみ追試した(下の図1)。15枚すべてのグラフは原論文参照。
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | # ===== ステップ2: 図1 主要指標の経年変化(全国平均±標準偏差、実データ追試) ===== # 原論文 図1-(a)〜(o) と同じ「全国平均値の推移+標準偏差」の描き方を、 # SSDSE-B-2026 で計算できる4指標について 2012〜2023年度で追試する。 items = [('老年人口割合', '老年人口割合 [%]'), ('高等学校卒業者進学率', '高等学校卒業者進学率 [%]'), ('一般診療所数_10万対', '一般診療所数(人口10万人あたり)'), ('人口増減率', '人口増減率 [人口千対]')] g = df.groupby('年度') fig, axes = plt.subplots(2, 2, figsize=(10, 7)) for ax, (col, label) in zip(axes.ravel(), items): m, s = g[col].mean(), g[col].std() ax.errorbar(m.index, m.values, yerr=s.values, color='#455A64', ecolor='#C62828', elinewidth=1, capsize=3, lw=1.5) ax.set_title(label, fontsize=11) ax.set_xlabel('年度') ax.grid(alpha=0.3) fig.suptitle('図1(追試)主要指標の経年変化:47都道府県の平均±標準偏差\n' '(SSDSE-B-2026、2012〜2023年度。原論文 図1 は 2005〜2016年度)', fontsize=12) fig.tight_layout(rect=[0, 0, 1, 0.93]) fig.savefig(f'{FIG_DIR}/2019_U2_fig1.png', bbox_inches='tight') plt.close(fig) print('【図1】全国平均の変化(2012年度 → 2023年度、実データ)') for col, label in items: print(f' {label}: {g[col].mean().iloc[0]:.2f} → {g[col].mean().iloc[-1]:.2f}') |
【図1】全国平均の変化(2012年度 → 2023年度、実データ) 老年人口割合 [%]: 25.62 → 31.59 高等学校卒業者進学率 [%]: 49.79 → 57.56 一般診療所数(人口10万人あたり): 79.58 → 84.50 人口増減率 [人口千対]: -3.95 → -10.22
groupby('年度') → mean() / std() — 各年度の47都道府県の平均と標準偏差。原論文 図1 の「全国平均値の推移及び標準偏差」と同じ集計です。ax.errorbar(..., yerr=s.values) — 平均値の折れ線にエラーバー(±1標準偏差)を重ねる、原論文 図1 と同じ描き方。原論文は15変数間の相関係数も確認している(巻末の補表2)。主な観察は:
本研究の中心は、15指標を説明変数、人口増減率を被説明変数とするパネルデータ分析である。モデルは次の重回帰型で表される(原論文 2節)。
Yit は第 i 都道府県の t 年度における人口増減率、Xj,it は15の説明変数、βj は回帰係数。ui は都道府県ごとに異なる individual effect(個体効果)で、これを定数とみなすのが固定効果モデル、確率変数とみなすのがランダム効果モデルである。原論文は両方を推定して比較した。
検定の流れを言葉にすると——「都道府県ごとの体質の違い(個体効果)は確かにある(F検定・LM検定)。では、その体質の違いは説明変数と相関しているか? 相関しているなら固定効果モデルしか使えないが、ハウスマン検定の結果(P=0.150)は無相関を否定しなかった。よってより効率的なランダム効果モデルの推定値を主に用いる」——これが原論文の判断である。
下表は原論文 表2 の転記である(原論文の報告値)。太字は5%水準で有意な変数(赤=負、オレンジ=正)。
| 説明変数 | 回帰係数 | 95%信頼区間 | P値 |
|---|---|---|---|
| 老年人口割合 [%] | −0.656 | −0.772 〜 −0.540 | <0.01 |
| 幼稚園数(3-5歳人口10万人あたり) | 0.002 | 0.000 〜 0.004 | 0.04 |
| 小学校数(6-11歳人口10万人あたり) | −0.002 | −0.008 〜 0.004 | 0.53 |
| 中学校数(12-14歳人口10万人あたり) | 0.001 | −0.007 〜 0.009 | 0.77 |
| 高等学校数(15-17歳人口10万人あたり) | −0.024 | −0.036 〜 −0.011 | <0.01 |
| 大学数(人口10万人あたり) | −0.074 | −1.833 〜 1.685 | 0.94 |
| 中学校卒業者進学率 | −0.284 | −0.557 〜 −0.011 | 0.04 |
| 高等学校卒業者進学率 | 0.125 | 0.068 〜 0.182 | <0.01 |
| 一般病院数(人口10万人あたり) | −0.119 | −0.360 〜 0.122 | 0.33 |
| 一般診療所数(人口10万人あたり) | −0.090 | −0.134 〜 −0.046 | <0.01 |
| 歯科診療所数(人口10万人あたり) | 0.110 | 0.010 〜 0.209 | 0.03 |
| 精神科病院数(人口10万人あたり) | 0.449 | −0.812 〜 1.711 | 0.49 |
| 医師数(人口10万人あたり) | 0.030 | 0.014 〜 0.045 | <0.01 |
| 歯科医師数(人口10万人あたり) | −0.024 | −0.068 〜 0.019 | 0.28 |
| 看護師・准看護師数(人口10万人あたり) | 0.000 | −0.003 〜 0.003 | 0.92 |
※ 原論文 表2 の報告値の転記。赤=負で有意、オレンジ=正で有意(P<0.05)。幼稚園数は係数0.002と小さいが、報告P値0.04で有意(信頼区間の下限は0.000)。
解析の結果、人口増加と有意に関連していたのは次の8変数である(原論文 4節):①老年人口割合の減少、②幼稚園数の増加、③高等学校数の減少、④中学校卒業者進学率の減少、⑤高等学校卒業者進学率の上昇、⑥一般診療所数の減少、⑦歯科診療所数の増加、⑧医師数の増加。
89 90 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 125 126 127 128 129 130 131 132 133 134 | # ===== ステップ3: 図2 原論文 表2(ランダム効果モデル)の報告値の可視化 ===== # 以下の数値は原論文 表2 の転記(回帰係数・95%信頼区間・P値)であり、再計算ではない。 paper_re = [ # (変数名, 係数, CI下限, CI上限, P値表記) ('老年人口割合 [%]', -0.656, -0.772, -0.540, '<0.01'), ('幼稚園数 (3-5歳人口10万対)', 0.002, 0.000, 0.004, '0.04'), ('小学校数 (6-11歳人口10万対)', -0.002, -0.008, 0.004, '0.53'), ('中学校数 (12-14歳人口10万対)', 0.001, -0.007, 0.009, '0.77'), ('高等学校数 (15-17歳人口10万対)', -0.024, -0.036, -0.011, '<0.01'), ('大学数 (人口10万対)', -0.074, -1.833, 1.685, '0.94'), ('中学校卒業者進学率', -0.284, -0.557, -0.011, '0.04'), ('高等学校卒業者進学率', 0.125, 0.068, 0.182, '<0.01'), ('一般病院数 (人口10万対)', -0.119, -0.360, 0.122, '0.33'), ('一般診療所数 (人口10万対)', -0.090, -0.134, -0.046, '<0.01'), ('歯科診療所数 (人口10万対)', 0.110, 0.010, 0.209, '0.03'), ('精神科病院数 (人口10万対)', 0.449, -0.812, 1.711, '0.49'), ('医師数 (人口10万対)', 0.030, 0.014, 0.045, '<0.01'), ('歯科医師数 (人口10万対)', -0.024, -0.068, 0.019, '0.28'), ('看護師・准看護師数 (人口10万対)', 0.000, -0.003, 0.003, '0.92'), ] fig, ax = plt.subplots(figsize=(9.6, 7.2)) ys = np.arange(len(paper_re))[::-1] for y, (name, b, lo, hi, p) in zip(ys, paper_re): sig = p.startswith('<') or float(p) < 0.05 # 原論文の報告P値で5%有意判定 color = ('#1565C0' if b > 0 else '#C62828') if sig else '#9E9E9E' ax.plot([lo, hi], [y, y], color=color, lw=2) ax.plot(b, y, 'o', color=color, ms=7) ax.text(1.80, y, f'P{p}' if p.startswith('<') else f'P={p}', va='center', fontsize=9, color='#333') ax.axvline(0, color='#555', lw=0.8, ls='--') ax.set_yticks(ys) ax.set_yticklabels([r[0] for r in paper_re], fontsize=10) ax.set_xlim(-2.0, 2.35) ax.set_xlabel('回帰係数(人口増減率[人口千対]への影響、95%信頼区間)') ax.set_title('図2:ランダム効果モデルによる解析結果\n' '(原論文 表2 の報告値の可視化。再計算ではない)\n' '青=正で有意 / 赤=負で有意 / 灰=有意でない(原論文の報告P値で判定)', fontsize=11) ax.grid(axis='x', alpha=0.3) fig.tight_layout() fig.savefig(f'{FIG_DIR}/2019_U2_fig2.png', bbox_inches='tight') plt.close(fig) is_sig = lambda p: p.startswith('<') or float(p) < 0.05 sig_pos = [r[0].split(' ')[0] for r in paper_re if is_sig(r[4]) and r[1] > 0] sig_neg = [r[0].split(' ')[0] for r in paper_re if is_sig(r[4]) and r[1] < 0] print('【図2】原論文 表2(ランダム効果モデル)の報告値') print(' 正で有意:', '、'.join(sig_pos)) print(' 負で有意:', '、'.join(sig_neg)) |
【図2】原論文 表2(ランダム効果モデル)の報告値 正で有意: 幼稚園数、高等学校卒業者進学率、歯科診療所数、医師数 負で有意: 老年人口割合、高等学校数、中学校卒業者進学率、一般診療所数
paper_re のリストは原論文 表2 の転記(回帰係数・95%信頼区間・P値)。ここでの再計算ではありません——医師数など SSDSE 未収録の変数を含むため再計算はできません。sig = not (lo <= 0 <= hi) — 95%信頼区間が0をまたがない=5%水準で有意、という読み方をそのままコードにしたもの。固定効果モデルによる解析でも、ランダム効果モデルと同様の傾向が認められた(原論文 補表1)。主な有意変数の係数を並べると:老年人口割合 −0.560(P<0.01)、幼稚園数 0.004(P=0.03)、高等学校数 −0.028(P<0.01)、高等学校卒業者進学率 0.133(P<0.01)、一般診療所数 −0.116(P=0.02)、医師数 0.022(P=0.05)。2つのモデルで符号と有意性がほぼ一致していることが、結果の頑健性を支えている。
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | # ===== ステップ6: 追試 — 11変数によるパネルデータ分析(FE・RE、期間・変数が異なる) ===== # 原論文と同型のモデル Y_it = α + Σβj X_j,it + u_i + ε_it を、SSDSE-B-2026 で # 計算可能な11変数・2012〜2023年度で推定する。医師数など4変数は未収録のため入らず、 # 学校数の分母も対象年齢人口ではなく総人口。原論文の係数の「検算」ではない点に注意。 xvars = ['老年人口割合', '幼稚園数_10万対', '小学校数_10万対', '中学校数_10万対', '高等学校数_10万対', '大学数_10万対', '中学校卒業者進学率', '高等学校卒業者進学率', '一般病院数_10万対', '一般診療所数_10万対', '歯科診療所数_10万対'] pdat = df[['都道府県', '年度', '人口増減率'] + xvars].dropna() y, X = pdat['人口増減率'], sm.add_constant(pdat[xvars]) # (1) プーリングOLS と 固定効果(LSDV)→ 個体効果の存在を F 検定 pool = sm.OLS(y, X).fit() Xd = pd.concat([X, pd.get_dummies(pdat['都道府県'], drop_first=True, dtype=float)], axis=1) lsdv = sm.OLS(y, Xd).fit() dfn, dfd = pdat['都道府県'].nunique() - 1, int(lsdv.df_resid) F = ((lsdv.rsquared - pool.rsquared) / dfn) / ((1 - lsdv.rsquared) / dfd) print(f'【追試】個体効果の F 検定: F({dfn}, {dfd}) = {F:.2f}, ' f'P = {stats.f.sf(F, dfn, dfd):.1e}(原論文: F(46,502)=13.82, P<0.001)') # (2) Breusch-Pagan の LM 検定(プーリングOLS残差から。ランダム効果の存在を検定) e = pool.resid T = pdat['年度'].nunique() S1 = pdat.assign(e=e).groupby('都道府県')['e'].sum().pow(2).sum() LM = len(pdat) * T / (2 * (T - 1)) * (S1 / (e ** 2).sum() - 1) ** 2 print(f' Breusch-Pagan LM 検定: LM = {LM:.1f}, ' f'P = {stats.chi2.sf(LM, 1):.1e}(原論文: P<0.001 → ランダム効果あり)') # (3) ランダム効果(変量切片)モデル: MixedLM で推定 re = sm.MixedLM(y, X, groups=pdat['都道府県']).fit(reml=True) ci = re.conf_int() print('\n【追試】ランダム効果モデル(SSDSE-B-2026、2012〜2023年度、11変数)') print(' ※ 期間・変数定義が異なるため原論文 表2 と数値は一致しない') paper_map = {r[0].split(' ')[0]: r for r in paper_re} print(f" {'変数': <11s}{'係数':>8s} {'95%信頼区間':>16s} {'P値':>6s} 原論文表2の係数") for v in xvars: key = v.replace('_10万対', '') pb = paper_map[key] ptxt = f'P{pb[4]}' if pb[4].startswith('<') else f'P={pb[4]}' star = '*' if re.pvalues[v] < 0.05 else ' ' print(f' {key: <11s}{re.params[v]:+8.3f} ' f'[{ci.loc[v, 0]:+.3f}, {ci.loc[v, 1]:+.3f}] {re.pvalues[v]:6.3f}{star} ' f'{pb[1]:+.3f} ({ptxt})') print(' (* は追試で5%有意。右端の欄は原論文 表2 の報告値)') |
【追試】個体効果の F 検定: F(46, 506) = 21.42, P = 3.5e-91(原論文: F(46,502)=13.82, P<0.001) Breusch-Pagan LM 検定: LM = 7257.8, P = 0.0e+00(原論文: P<0.001 → ランダム効果あり) 【追試】ランダム効果モデル(SSDSE-B-2026、2012〜2023年度、11変数) ※ 期間・変数定義が異なるため原論文 表2 と数値は一致しない 変数 係数 95%信頼区間 P値 原論文表2の係数 老年人口割合 -0.492 [-0.585, -0.399] 0.000* -0.656 (P<0.01) 幼稚園数 +0.158 [+0.077, +0.238] 0.000* +0.002 (P=0.04) 小学校数 -0.059 [-0.222, +0.105] 0.482 -0.002 (P=0.53) 中学校数 -0.495 [-0.841, -0.149] 0.005* +0.001 (P=0.77) 高等学校数 -0.528 [-1.060, +0.004] 0.052 -0.024 (P<0.01) 大学数 -0.782 [-2.404, +0.839] 0.344 -0.074 (P=0.94) 中学校卒業者進学率 +0.445 [+0.324, +0.567] 0.000* -0.284 (P=0.04) 高等学校卒業者進学率 -0.099 [-0.156, -0.042] 0.001* +0.125 (P<0.01) 一般病院数 -0.039 [-0.293, +0.216] 0.765 -0.119 (P=0.33) 一般診療所数 -0.022 [-0.066, +0.022] 0.332 -0.090 (P<0.01) 歯科診療所数 +0.148 [+0.065, +0.231] 0.000* +0.110 (P=0.03) (* は追試で5%有意。右端の欄は原論文 表2 の報告値)
sm.MixedLM(..., groups=都道府県)(変量切片モデル)で推定。老年人口割合(負)・幼稚園数(正)・歯科診療所数(正)は原論文 表2 と同じ向きで有意でした。回帰結果の解釈を補強するため、原論文は2005〜2016年度の12年間、人口増減率が常に正であった5都道府県——埼玉県・東京都・神奈川県・愛知県・沖縄県——を取り出し、有意だった2つの指標の推移を個別に確認している。
高等学校卒業者進学率(高等教育機関への進学率)は日本全体ではここ数年頭打ちとされる(原論文の引用する学校基本調査)。しかしこの5都道府県では概ね増加傾向にあり、2016年度の値は2005年度と比較していずれの都道府県でも上昇していた——高等教育機関への進学率の上昇が人口増加に寄与する可能性を支持する観察である。
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | # ===== ステップ4: 図3 人口増加が続いた5都道府県の高等学校卒業者進学率(実データ追試) ===== # 原論文 図2: 2005〜2016年度に人口増減率が常に正だった5都道府県 # (埼玉・東京・神奈川・愛知・沖縄)の高等学校卒業者進学率の推移。 # ここでは同じ5都道府県を SSDSE-B-2026(2012〜2023年度)で追試する。 five = ['埼玉県', '東京都', '神奈川県', '愛知県', '沖縄県'] colors5 = ['#1565C0', '#C62828', '#2E7D32', '#6A1B9A', '#E65100'] fig, ax = plt.subplots(figsize=(9, 5)) for pref, c in zip(five, colors5): sub = df[df['都道府県'] == pref].sort_values('年度') ax.plot(sub['年度'], sub['高等学校卒業者進学率'], marker='o', ms=4, color=c, label=pref) ax.set_xlabel('年度') ax.set_ylabel('高等学校卒業者進学率 [%]') ax.set_title('図3(追試)人口増加が続いた5都道府県の高等学校卒業者進学率\n' '(SSDSE-B-2026、2012〜2023年度。原論文 図2 は 2005〜2016年度)', fontsize=11) ax.legend(loc='lower right', fontsize=10) ax.grid(alpha=0.3) fig.tight_layout() fig.savefig(f'{FIG_DIR}/2019_U2_fig3.png', bbox_inches='tight') plt.close(fig) print('【図3】5都道府県の高等学校卒業者進学率(2012→2023年度、実データ)') for pref in five: sub = df[df['都道府県'] == pref].sort_values('年度') print(f" {pref}: {sub['高等学校卒業者進学率'].iloc[0]:.1f}% → " f"{sub['高等学校卒業者進学率'].iloc[-1]:.1f}%") |
【図3】5都道府県の高等学校卒業者進学率(2012→2023年度、実データ) 埼玉県: 56.4% → 65.8% 東京都: 65.1% → 74.1% 神奈川県: 60.2% → 69.4% 愛知県: 58.3% → 64.0% 沖縄県: 38.2% → 46.7%
df[df['都道府県'] == pref] — 都道府県名でパネルデータから1本の時系列を取り出す基本操作。同じ5都道府県について、原論文 図3 は人口10万人あたり医師数の推移を示している。医師数は SSDSE-B-2026 に収録されていないため本ページでは再現できない(グラフは原論文参照)。原論文が図3から読み取った内容は:
では、この「人口増加が続く5都道府県」という構図は最近のデータでも維持されているのだろうか。SSDSE-B-2026(2012〜2023年度)で同じ判定をやり直してみる。
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | # ===== ステップ5: 図4 2023年度の人口増減率ランキング+「常に正」の検証(実データ) ===== always_pos = [p for p, s in df.groupby('都道府県')['人口増減率'] if (s > 0).all()] print('【検証】2012〜2023年度に人口増減率が常に正だった都道府県:', '、'.join(always_pos) if always_pos else 'なし') latest = df[df['年度'] == 2023].sort_values('人口増減率') fig, ax = plt.subplots(figsize=(8.5, 11)) cols = ['#1565C0' if v > 0 else ('#E65100' if p in five else '#B0BEC5') for v, p in zip(latest['人口増減率'], latest['都道府県'])] ax.barh(range(len(latest)), latest['人口増減率'], color=cols, height=0.65) ax.set_yticks(range(len(latest))) ax.set_yticklabels(latest['都道府県'], fontsize=9) ax.axvline(0, color='#555', lw=0.8) ax.set_xlabel('人口増減率 [人口千対](自然増減率+社会増減率)') ax.set_title('図4:2023年度の都道府県別人口増減率(SSDSE-B-2026 から計算した実データ)\n' '青=プラス / オレンジ=原論文の「12年間常に正」だった5都道府県のうちマイナスの県', fontsize=11) ax.grid(axis='x', alpha=0.3) fig.tight_layout() fig.savefig(f'{FIG_DIR}/2019_U2_fig4.png', bbox_inches='tight') plt.close(fig) top3 = latest.tail(3)[['都道府県', '人口増減率']].iloc[::-1] print('【図4】2023年度の人口増減率 上位3:', ' / '.join(f'{r.都道府県} {r.人口増減率:+.2f}' for r in top3.itertuples())) print(' 原論文の5都道府県の2023年度値:', ' / '.join(f"{p} {latest.set_index('都道府県').loc[p, '人口増減率']:+.2f}" for p in five)) |
【検証】2012〜2023年度に人口増減率が常に正だった都道府県: なし 【図4】2023年度の人口増減率 上位3: 東京都 +0.56 / 沖縄県 -2.22 / 神奈川県 -2.53 原論文の5都道府県の2023年度値: 埼玉県 -3.32 / 東京都 +0.56 / 神奈川県 -2.53 / 愛知県 -4.84 / 沖縄県 -2.22
(s > 0).all() — その都道府県の人口増減率が全年度で正なら True。原論文の「2005〜2016年度の12年間常に正であった5都道府県」の判定を 2012〜2023年度でやり直します。幼稚園数の増加は人口増加と有意に関連していた。原論文は、2015年4月施行の子ども・子育て支援新制度(認定こども園・幼稚園・保育所・地域型保育の「量的拡充」と質の向上を掲げる)に触れ、幼稚園を始めとする子どもの養育施設の充実が「子どもを産み育てやすい環境づくり」につながり、人口増加に結びついたのではないかと解釈している。
高等学校卒業者進学率の上昇は人口増加と有意に関連しており(係数0.125、P<0.01)、5都道府県の推移(図3)とも整合的だった。高等教育機関への進学率の上昇が人口増加に寄与する可能性が示唆された。
人口10万人あたりの歯科診療所数(係数0.110、P=0.03)や医師数(係数0.030、P<0.01)の増加が人口増加に寄与する可能性が示唆された。急速に少子高齢化が進む我が国では医療・介護の提供体制の整備が喫緊の課題であり、医師偏在——特に地方での医師不足が深刻な問題となっている。原論文は、人口増加が続いた5都道府県が概ね大都市を含み医師数を十分確保できたことを踏まえ、「これら以外の都道府県、特に地方でも同様に医師数を増やしていくための政策を推進していくことが必要」と提言している。
この論文(とパネルデータ分析全般)を読むときに、初心者が陥りやすい誤解を整理します。
本文中の 下線付き用語 はクリックすると詳しい解説がポップアップします。ここでは特に重要な用語をまとめます。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
このページのスクリプト(code/2019_U2_yushu.py)を出発点に、難易度順の5つの課題に挑戦してみましょう。
items リストを書き換えて、幼稚園数・小学校数・一般病院数など別の指標の経年変化(平均±標準偏差)を描いてみよう。原論文が観察した「幼稚園〜高等学校数の減少」「一般病院数の一貫した減少」は 2012〜2023年度でも見えるだろうか?
(s > 0).all() を .any() や期間スライスに変えて確かめよう。
人口増減率 を 自然増減率・社会増減率 に差し替えて2本のランダム効果モデルを推定し、係数を比較しよう。幼稚園数はどちらに効くか? 進学率は?(発展の可能性②の実装)
groupby('都道府県').shift(1))に置き換えたモデルを推定し、同時点モデルと係数を比較しよう。医師数や診療所数の係数はどう変わるか? それでも因果とは言い切れない理由を、自分の言葉で説明できれば合格。
本論文で学んだパネルデータ分析は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。
この論文を理解できたか、クリックで確認しましょう。間違えても解説が出ます。
このページの分析は、この画面の中でそのまま実行できます。
Python をインストールする必要も、CSV をダウンロードする必要もありません。
下のセルの 「▶ ブラウザで実行」 を上から順に押すか、
「▶ 最初から全部実行」 で一気に流してください。
表示されるのは、本文の図表とまったく同じ計算の結果です
(動かしているのは再現スクリプト code/2019_U2_yushu.py そのもの)。
コードは書き換えられます。「✏️ 書き換える」で数字や変数を変えて ▶ を押すと、 結果がどう変わるかをその場で確かめられます(元に戻すボタンつき)。 ページを開いた時点で裏で実行環境の準備が始まっているので、待ち時間はほとんどありません。 初回だけ実行環境の取得にインターネット接続が必要です。