このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
日本の社会保障給付費は2022年度で約134兆円に達し、GDP比で24%を超える。その配分は都道府県によって大きく異なり、高齢化が進む地方と都市部では、福祉ニーズの性質・規模・資源制約が根本的に異なる。本研究は、SSDSE-B(都道府県統計)を用いて、保健医療費支出と高齢化・経済状況の関係を定量的に分析した。
まず「生活保護・社会福祉支出と地域経済格差の分析」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。
SSDSE-B Pearson相関 OLS重回帰 地域比較
SSDSE-B(社会・人口統計体系データセット B 都道府県版)2026年版より、2022年度の47都道府県データを使用。生活保護費や老人福祉費の直接データはSSDS-Bに収録されていないため、保健医療費(消費支出内訳)と高齢化・人口移動指標を組み合わせて分析する。
| 役割 | 変数名 | 定義・単位 | 出典項目 |
|---|---|---|---|
| 目的変数 | 保健医療費 | 二人以上世帯の月間保健医療費(円) | 保健医療費(二人以上の世帯) |
| 説明変数 | 高齢化率 | 65歳以上人口 ÷ 総人口 × 100(%) | 65歳以上人口 / 総人口(計算) |
| 転出率 | 転出者数 ÷ 総人口 × 1000(‰) | 転出者数 / 総人口(計算) | |
| 求人倍率 | 有効求人数 ÷ 有効求職者数(倍) | 月間有効求人数 / 月間有効求職者数 | |
| 消費支出 | 二人以上世帯の月間消費支出(円) | 消費支出(二人以上の世帯) |
| 変数 | 平均 | 標準偏差 | 最小 | 最大 |
|---|---|---|---|---|
| 保健医療費(円/世帯) | 14,390 | 2,007 | 9,411(青森) | 19,107(愛知) |
| 高齢化率(%) | 31.4 | 3.3 | 22.8(沖縄) | 38.6(秋田) |
| 転出率(‰) | 16.9 | 2.6 | 10.3(北海道) | 26.0(東京) |
| 求人倍率(倍) | 1.39 | 0.25 | 0.88 | 1.94 |
| 消費支出(円/世帯) | 289,630 | 19,187 | 245,054 | 324,793 |
2022年の都道府県別保健医療費(月額、二人以上の世帯)を地域ブロック別に色分けしてランキング表示した。愛知県(19,107円)や富山県、石川県など中部・関東ブロックで高い傾向が見られる一方、青森県(9,411円)や東北・北海道ブロックで低くなっている。
ランキング棒グラフでは、値の昇順・降順にソートすることで地域パターンが視覚的に把握しやすくなる。地域ブロックで色分けすることで、「空間的な偏り」を棒グラフ単体で表現できる。地図がなくても地域格差を伝えられるのがポイント。
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)。f"...{x}..." はf-string。文字列の中に {変数} と書くだけで埋め込めて、{x:.2f} のように書式も指定できます。17 18 19 20 21 22 23 24 | # ── データ読込 ────────────────────────────────────────── 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年断面 df22 = df_b[df_b['年度'] == 2022].copy() assert len(df22) == 47, f"47都道府県が必要ですが {len(df22)} 行のみ取得" |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。pd.read_csv(...) でCSVを読み込みます。encoding='cp932' は日本語Windows由来の文字コード、header=1 は「2行目を列名として使う」。df['地域コード'].str.match(r'^R\d{5}', ...) — 正規表現で「R+数字5桁」の行(47都道府県)だけTrueにし、真偽値で行をフィルタ。.astype(int) — 列を整数に変換(年度などを数値比較するため)。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | # ── 派生変数の計算 ────────────────────────────────────── # 高齢化率(%) df22['高齢化率'] = df22['65歳以上人口'] / df22['総人口'] * 100 # 転出率(1000人あたり転出者数) df22['転出率'] = df22['転出者数(日本人移動者)'] / df22['総人口'] * 1000 # 求人倍率代理(有効求人数 / 有効求職者数) df22['求人倍率'] = df22['月間有効求人数(一般)'] / df22['月間有効求職者数(一般)'] # 保育所充足率(定員/在所児数) df22['保育充足率'] = df22['保育所等定員数'] / df22['保育所等在所児数'] # 1人あたり保健医療費(目的変数として使用) df22['保健医療費_1人'] = df22['保健医療費(二人以上の世帯)'] # 消費支出(生活水準の代理) df22['消費支出'] = df22['消費支出(二人以上の世帯)'] # 待機児童率 df22['待機児童率'] = df22['保育所等利用待機児童数'] / df22['保育所等定員数'] * 100 |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。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 | # 地域マップ region_map = { '北海道': '北海道・東北', '青森県': '北海道・東北', '岩手県': '北海道・東北', '宮城県': '北海道・東北', '秋田県': '北海道・東北', '山形県': '北海道・東北', '福島県': '北海道・東北', '茨城県': '関東', '栃木県': '関東', '群馬県': '関東', '埼玉県': '関東', '千葉県': '関東', '東京都': '関東', '神奈川県': '関東', '新潟県': '中部', '富山県': '中部', '石川県': '中部', '福井県': '中部', '山梨県': '中部', '長野県': '中部', '岐阜県': '中部', '静岡県': '中部', '愛知県': '中部', '三重県': '近畿', '滋賀県': '近畿', '京都府': '近畿', '大阪府': '近畿', '兵庫県': '近畿', '奈良県': '近畿', '和歌山県': '近畿', '鳥取県': '中国・四国', '島根県': '中国・四国', '岡山県': '中国・四国', '広島県': '中国・四国', '山口県': '中国・四国', '徳島県': '中国・四国', '香川県': '中国・四国', '愛媛県': '中国・四国', '高知県': '中国・四国', '福岡県': '九州・沖縄', '佐賀県': '九州・沖縄', '長崎県': '九州・沖縄', '熊本県': '九州・沖縄', '大分県': '九州・沖縄', '宮崎県': '九州・沖縄', '鹿児島県': '九州・沖縄', '沖縄県': '九州・沖縄' } region_colors = { '北海道・東北': '#4e9af1', '関東': '#e05c5c', '中部': '#f0a500', '近畿': '#5cb85c', '中国・四国': '#9b59b6', '九州・沖縄': '#f39c12' } df22['地域'] = df22['都道府県'].map(region_map) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。67 68 69 70 71 72 73 74 75 76 77 78 | # ── 分析変数の確認 ────────────────────────────────────── print("=== 2022年 基本統計量 ===") vars_show = ['高齢化率', '転出率', '求人倍率', '保健医療費_1人', '消費支出'] print(df22[vars_show].describe().round(2)) # ── 図1: 保健医療費/世帯 都道府県別ランキング(地域色分け棒グラフ) ─ print("\n=== 図1: 保健医療費ランキング ===") df_rank = df22[['都道府県', '保健医療費_1人', '地域']].sort_values('保健医療費_1人', ascending=True) fig, ax = plt.subplots(figsize=(10, 11)) colors = [region_colors[r] for r in df_rank['地域']] bars = ax.barh(df_rank['都道府県'], df_rank['保健医療費_1人'], color=colors, edgecolor='white', linewidth=0.4) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。.describe() — 件数・平均・標準偏差・四分位・最大/最小を一括計算。データの素性チェックに必須。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。79 80 81 82 83 84 85 86 87 | # 値ラベル for bar, val in zip(bars, df_rank['保健医療費_1人']): ax.text(val + 100, bar.get_y() + bar.get_height()/2, f'{int(val):,}', va='center', ha='left', fontsize=7.5) ax.set_xlabel('保健医療費(円/世帯・月)', fontsize=11) ax.set_title('都道府県別 保健医療費(2022年)\n地域別色分け', fontsize=13, fontweight='bold', pad=10) ax.set_xlim(0, df_rank['保健医療費_1人'].max() * 1.20) ax.tick_params(axis='y', labelsize=8.5) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。88 89 90 91 92 93 94 95 96 97 98 99 | # 凡例 from matplotlib.patches import Patch legend_elements = [Patch(facecolor=c, label=r) for r, c in region_colors.items()] ax.legend(handles=legend_elements, loc='lower right', fontsize=9, title='地域', title_fontsize=9) ax.grid(axis='x', linestyle='--', alpha=0.4) ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) plt.tight_layout() out1 = os.path.join(FIG_DIR, '2020_H4_fig1.png') plt.savefig(out1, dpi=150, bbox_inches='tight') plt.close() |
=== 2022年 基本統計量 ===
高齢化率 転出率 求人倍率 保健医療費_1人 消費支出
count 47.00 47.00 47.00 47.00 47.00
mean 31.35 16.91 1.39 14389.77 289630.36
std 3.27 2.61 0.25 2007.32 19186.91
min 22.81 10.33 0.88 9411.00 245054.00
25% 29.85 15.31 1.18 12567.50 276834.50
50% 31.42 16.88 1.43 14486.00 287781.00
75% 33.72 17.99 1.57 15743.00 302255.00
max 38.60 26.03 1.94 19107.00 324793.00
=== 図1: 保健医療費ランキング ===import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。まず保健医療費と各指標のPearson相関係数を網羅的に確認した。保健医療費との相関が最も強いのは消費支出(r=0.70、p<0.01)、次いで高齢化率(r=−0.47、p<0.01)、転出率(r=0.39、p<0.01)であった。
| 変数 | r | 有意性 | 解釈 |
|---|---|---|---|
| 消費支出 | +0.70** | p<0.01 | 生活水準が高い都道府県ほど保健医療費も高い |
| 高齢化率 | −0.47** | p<0.01 | 高齢化が進む地域ほど(相対的に)保健医療費が低い |
| 転出率 | +0.39** | p<0.01 | 人口流出が多い地域(都市圏?)で保健医療費が高め |
| 求人倍率 | −0.15 | n.s. | 有意な関係なし |
高齢化率と保健医療費の間には 負の相関(r = −0.468, p = 0.0009) が確認された。高齢化が進む東北・北海道地域で保健医療費が低く、比較的若い関東・中部で高い逆説的なパターンが見られる。
目的変数を保健医療費(標準化)、説明変数を高齢化率・転出率・求人倍率・消費支出(いずれも標準化)として重回帰分析を実施した。
| 変数 | 標準化係数 β | t値 | p値 | 95%CI | 有意性 |
|---|---|---|---|---|---|
| 消費支出 | +0.612 | 5.620 | <0.001 | [0.393, 0.832] | *** |
| 転出率 | +0.220 | 1.860 | 0.070 | [−0.019, 0.459] | † |
| 高齢化率 | −0.133 | −1.028 | 0.310 | [−0.394, 0.128] | n.s. |
| 求人倍率 | −0.008 | −0.073 | 0.942 | [−0.235, 0.218] | n.s. |
† p<0.10 *** p<0.001 Adj. R² = 0.535 F(4,42) = 14.21 p<0.001
変数の単位が異なる(%、円、倍)場合、偏回帰係数をそのまま比較することはできない。各変数を平均0・標準偏差1に標準化してから回帰すると、係数β(標準化偏回帰係数)が「1標準偏差変化したときの目的変数の変化量(標準偏差単位)」となり、説明変数間で影響力の大きさを直接比較できる。
高齢化率と保健医療費の単純相関はr=−0.47(有意)だったが、重回帰で消費支出を統制すると高齢化率の係数は有意でなくなった。これは「交絡(confounding)」の例。高齢化率と消費支出は相関しており(r=−0.36)、消費支出が真の決定要因である可能性が高い。相関係数だけで因果を語ることの危険性を示す重要な事例。
101 102 103 104 105 106 107 108 109 110 111 112 | print(f" 保存: {out1}") # ── 図2: 高齢化率 vs 保健医療費 散布図(地域色分け・回帰線・ラベル) ── print("\n=== 図2: 高齢化率 vs 保健医療費 ===") r, p = stats.pearsonr(df22['高齢化率'], df22['保健医療費_1人']) print(f" r = {r:.3f}, p = {p:.4f}") fig, ax = plt.subplots(figsize=(10, 7)) for region, grp in df22.groupby('地域'): ax.scatter(grp['高齢化率'], grp['保健医療費_1人'], color=region_colors[region], label=region, s=65, zorder=3, edgecolors='white', linewidth=0.6) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df.groupby('列').apply(関数) — グループごとに関数を適用。時系列や地域別の集計でよく使います。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | # ラベル for _, row in df22.iterrows(): ax.annotate(row['都道府県'], (row['高齢化率'], row['保健医療費_1人']), fontsize=6.5, xytext=(3, 2), textcoords='offset points', color='#333') # 回帰直線 x_line = np.linspace(df22['高齢化率'].min(), df22['高齢化率'].max(), 100) slope, intercept = np.polyfit(df22['高齢化率'], df22['保健医療費_1人'], 1) ax.plot(x_line, slope * x_line + intercept, 'k--', linewidth=1.5, label=f'回帰線 (r={r:.3f}{"*" if p < 0.05 else ""})') ax.set_xlabel('高齢化率(%)', fontsize=11) ax.set_ylabel('保健医療費(円/世帯・月)', fontsize=11) ax.set_title('高齢化率と保健医療費の関係(2022年, n=47)', fontsize=13, fontweight='bold') ax.legend(fontsize=9, loc='upper left') ax.grid(linestyle='--', alpha=0.4) ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。for _, row in df.iterrows() — DataFrameを1行ずつ取り出すループ。1点ずつ描画したいときに使用。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。131 132 133 134 135 136 137 138 139 140 | # 統計注記 p_str = f"p={p:.4f}" if p >= 0.0001 else "p<0.0001" ax.text(0.98, 0.04, f'r = {r:.3f}, {p_str}', transform=ax.transAxes, ha='right', fontsize=10, bbox=dict(boxstyle='round,pad=0.4', facecolor='#fff9c4', edgecolor='#f9a825')) plt.tight_layout() out2 = os.path.join(FIG_DIR, '2020_H4_fig2.png') plt.savefig(out2, dpi=150, bbox_inches='tight') plt.close() |
保存: html/figures/2020_H4_fig1.png === 図2: 高齢化率 vs 保健医療費 === r = -0.468, p = 0.0009
fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。6つの地域ブロック別に保健医療費・高齢化率・消費支出・転出率の平均値を集計し、地域格差のパターンを分析した。
| 地域ブロック | 都道府県数 | 保健医療費 平均(円/世帯) | 高齢化率 平均(%) | 消費支出 平均(円/世帯) | 転出率 平均(‰) |
|---|---|---|---|---|---|
| 関東 | 7 | 15,719 | 27.9 | 308,304 | 19.4 |
| 近畿 | 7 | 15,016 | 30.1 | 289,631 | 17.6 |
| 中部 | 9 | 15,006 | 31.0 | 301,099 | 14.7 |
| 九州・沖縄 | 8 | 14,516 | 31.3 | 276,695 | 18.2 |
| 中国・四国 | 9 | 13,700 | 33.5 | 283,917 | 16.6 |
| 北海道・東北 | 7 | 12,384 | 33.9 | 278,340 | 15.5 |
ブロック平均は都道府県間の格差を均してしまう。中部ブロック内でも愛知(19,107円)と山梨・新潟では大きな差がある。地域ブロック分析は全体像の把握には有効だが、個別都道府県の分析(n=47の散布図)と組み合わせることで、より正確な理解が得られる。
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | print(f" 保存: {out2}") # ── 図3: 相関ヒートマップ ────────────────────────────────── print("\n=== 図3: 相関ヒートマップ ===") corr_vars = { '保健医療費': '保健医療費_1人', '消費支出': '消費支出', '高齢化率': '高齢化率', '転出率': '転出率', '求人倍率': '求人倍率', '保育充足率': '保育充足率', '待機児童率': '待機児童率', } df_corr = df22[[v for v in corr_vars.values()]].rename(columns={v: k for k, v in corr_vars.items()}) corr_matrix = df_corr.corr() |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | # p値行列 n = len(df_corr) p_matrix = pd.DataFrame(np.ones((len(corr_matrix), len(corr_matrix))), index=corr_matrix.index, columns=corr_matrix.columns) for c1 in corr_matrix.columns: for c2 in corr_matrix.columns: if c1 != c2: _, p_val = stats.pearsonr(df_corr[c1].dropna(), df_corr[c2].dropna()) p_matrix.loc[c1, c2] = p_val fig, ax = plt.subplots(figsize=(8, 7)) import matplotlib.colors as mcolors cmap = plt.cm.RdBu_r im = ax.imshow(corr_matrix.values, cmap=cmap, vmin=-1, vmax=1, aspect='auto') plt.colorbar(im, ax=ax, shrink=0.82, label='Pearson r') labels = list(corr_matrix.columns) ax.set_xticks(range(len(labels))) ax.set_yticks(range(len(labels))) ax.set_xticklabels(labels, fontsize=10, rotation=30, ha='right') ax.set_yticklabels(labels, fontsize=10) for i in range(len(labels)): for j in range(len(labels)): val = corr_matrix.iloc[i, j] p_val = p_matrix.iloc[i, j] star = '**' if p_val < 0.01 else ('*' if p_val < 0.05 else '') txt_color = 'white' if abs(val) > 0.6 else 'black' ax.text(j, i, f'{val:.2f}{star}', ha='center', va='center', fontsize=8.5, color=txt_color, fontweight='bold' if star else 'normal') ax.set_title('福祉・経済指標の相関ヒートマップ(2022年)\n* p<0.05 ** p<0.01', fontsize=12, fontweight='bold', pad=10) plt.tight_layout() out3 = os.path.join(FIG_DIR, '2020_H4_fig3.png') plt.savefig(out3, dpi=150, bbox_inches='tight') plt.close() |
保存: html/figures/2020_H4_fig2.png === 図3: 相関ヒートマップ ===
import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。本分析の結果を踏まえ、社会福祉支出と地域経済格差の是正に向けた示唆を整理する。
195 196 197 198 199 200 201 202 203 204 205 | print(f" 保存: {out3}") print(corr_matrix.round(3)) # ── 重回帰分析 ──────────────────────────────────────────── print("\n=== 重回帰分析 ===") X_cols_raw = ['高齢化率', '転出率', '求人倍率', '消費支出'] X_cols_disp = ['高齢化率', '転出率', '求人倍率', '消費支出'] y_col = '保健医療費_1人' df_reg = df22[X_cols_raw + [y_col]].dropna() print(f" 回帰サンプル数: {len(df_reg)}") |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。206 207 208 209 210 211 212 213 214 215 | # 標準化 df_std = df_reg.copy() for col in X_cols_raw: df_std[col] = (df_reg[col] - df_reg[col].mean()) / df_reg[col].std() df_std[y_col] = (df_reg[y_col] - df_reg[y_col].mean()) / df_reg[y_col].std() X = sm.add_constant(df_std[X_cols_raw]) y = df_std[y_col] result = sm.OLS(y, X).fit() print(result.summary()) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。sm.add_constant(X) — 切片項(定数1の列)を先頭に追加。statsmodelsで必須。sm.OLS(y, X).fit() — 最小二乗法でモデルを推定。model.params, model.pvalues, model.conf_int() で結果取得。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。216 217 218 219 220 221 222 223 224 225 | # 係数・信頼区間 coef_df = pd.DataFrame({ '変数': X_cols_disp, '標準化係数': result.params[X_cols_raw].values, 'p値': result.pvalues[X_cols_raw].values, 'CI下限': result.conf_int().loc[X_cols_raw, 0].values, 'CI上限': result.conf_int().loc[X_cols_raw, 1].values, }) print("\n標準化偏回帰係数:") print(coef_df.round(4)) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。226 227 228 229 230 231 232 233 234 | # ── 図4: 標準化偏回帰係数プロット ────────────────────────── print("\n=== 図4: 標準化偏回帰係数プロット ===") coef_sorted = coef_df.sort_values('標準化係数') fig, ax = plt.subplots(figsize=(9, 5)) y_pos = range(len(coef_sorted)) bar_colors = ['#e05c5c' if v > 0 else '#4e9af1' for v in coef_sorted['標準化係数']] bars = ax.barh(y_pos, coef_sorted['標準化係数'], color=bar_colors, edgecolor='white', linewidth=0.5, height=0.55) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | # 信頼区間(エラーバー) for i, (_, row) in enumerate(coef_sorted.iterrows()): ax.plot([row['CI下限'], row['CI上限']], [i, i], 'k-', linewidth=2.2, zorder=4) ax.plot([row['CI下限'], row['CI上限']], [i, i], 'k|', markersize=10, zorder=4) # 値ラベル for bar, (_, row) in zip(bars, coef_sorted.iterrows()): x_pos = row['標準化係数'] star = '**' if row['p値'] < 0.01 else ('*' if row['p値'] < 0.05 else ' (n.s.)') offset = 0.005 if x_pos >= 0 else -0.005 ha = 'left' if x_pos >= 0 else 'right' ax.text(x_pos + offset, bar.get_y() + bar.get_height()/2, f'{x_pos:.3f}{star}', va='center', ha=ha, fontsize=9.5) ax.axvline(0, color='black', linewidth=0.8) ax.set_yticks(y_pos) ax.set_yticklabels(coef_sorted['変数'], fontsize=11) ax.set_xlabel('標準化偏回帰係数(β)', fontsize=11) ax.set_title(f'保健医療費の決定要因(標準化偏回帰係数)\n' f'目的変数: 保健医療費/世帯 Adj. R² = {result.rsquared_adj:.3f}', fontsize=12, fontweight='bold', pad=10) ax.set_xlim(coef_sorted['CI下限'].min() * 1.3, coef_sorted['CI上限'].max() * 1.3) ax.grid(axis='x', linestyle='--', alpha=0.4) ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) note = '* p<0.05 ** p<0.01 エラーバー: 95%信頼区間' ax.text(0.99, 0.02, note, transform=ax.transAxes, fontsize=9, ha='right', color='#555') plt.tight_layout() out4 = os.path.join(FIG_DIR, '2020_H4_fig4.png') plt.savefig(out4, dpi=150, bbox_inches='tight') plt.close() |
保存: html/figures/2020_H4_fig3.png
保健医療費 消費支出 高齢化率 転出率 求人倍率 保育充足率 待機児童率
保健医療費 1.000 0.696 -0.468 0.388 -0.148 -0.148 0.053
消費支出 0.696 1.000 -0.361 0.161 -0.020 0.040 -0.068
高齢化率 -0.468 -0.361 1.000 -0.504 0.391 0.245 -0.471
転出率 0.388 0.161 -0.504 1.000 -0.342 -0.310 0.269
求人倍率 -0.148 -0.020 0.391 -0.342 1.000 0.280 -0.517
保育充足率 -0.148 0.040 0.245 -0.310 0.280 1.000 -0.328
待機児童率 0.053 -0.068 -0.471 0.269 -0.517 -0.328 1.000
=== 重回帰分析 ===
回帰サンプル数: 47
OLS Regression Results
==============================================================================
Dep. Variable: 保健医療費_1人 R-squared: 0.575
Model: OLS Adj. R-squared: 0.535
Method: Least Squares F-statistic: 14.21
Date: Mon, 18 May 2026 Prob (F-statistic): 2.04e-07
Time: 11:23:37 Log-Likelihood: -46.070
No. Observations: 47 AIC: 102.1
Df Residuals: 42 BIC: 111.4
Df Model: 4
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const -1.839e-16 0.100 -1.85e-15 1.000 -0.201 0.201
高齢化率 -0.1328 0.129 -1.028 0.310 -0.394 0.128
転出率 0.2203 0.118 1.860 0.070 -0.019 0.459
求人倍率 -0.0082 0.112 -0.073 0.942 -0.235 0.218
消費支出 0.6124 0.109 5.620 0.000 0.392 0.832
==============================================================================
Omnibus: 1.161 Durbin-Watson: 1.945
Prob(Omnibus): 0.560 Jarque-Bera (JB): 1.020
Skew: 0.348 Prob(JB): 0.600
Kurtosis: 2.812 Cond. No. 2.14
==============================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
標準化偏回帰係数:
変数 標準化係数 p値 CI下限 CI上限
0 高齢化率 -0.1328 0.3100 -0.3936 0.1280
1 転出率 0.2203 0.0699 -0.0187 0.4593
2 求人倍率 -0.0082 0.9424 -0.2347 0.2183
3 消費支出 0.6124 0.0000 0.3925 0.8323
=== 図4: 標準化偏回帰係数プロット ===ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。for _, row in df.iterrows() — DataFrameを1行ずつ取り出すループ。1点ずつ描画したいときに使用。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。269 270 271 272 273 274 275 276 277 278 279 | print(f" 保存: {out4}") # ── 地域別集計(HTML用) ───────────────────────────────── print("\n=== 地域別集計 ===") region_stats = df22.groupby('地域').agg( 保健医療費平均=('保健医療費_1人', 'mean'), 高齢化率平均=('高齢化率', 'mean'), 消費支出平均=('消費支出', 'mean'), 転出率平均=('転出率', 'mean'), ).round(1) print(region_stats) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df.groupby('列').apply(関数) — グループごとに関数を適用。時系列や地域別の集計でよく使います。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | # ── 要約統計 ────────────────────────────────────────────── print("\n=== 要約統計 ===") print(f"保健医療費 全国平均: {df22['保健医療費_1人'].mean():.0f} 円/世帯") print(f"保健医療費 最大: {df22['保健医療費_1人'].max():.0f} ({df22.loc[df22['保健医療費_1人'].idxmax(), '都道府県']})") print(f"保健医療費 最小: {df22['保健医療費_1人'].min():.0f} ({df22.loc[df22['保健医療費_1人'].idxmin(), '都道府県']})") print(f"高齢化率 全国平均: {df22['高齢化率'].mean():.1f}%") print(f"高齢化率 最大: {df22['高齢化率'].max():.1f}% ({df22.loc[df22['高齢化率'].idxmax(), '都道府県']})") print(f"R²: {result.rsquared:.3f}, Adj.R²: {result.rsquared_adj:.3f}") print(f"F統計量: {result.fvalue:.3f}, p値: {result.f_pvalue:.4f}") print(f"高齢化率 vs 保健医療費 r={r:.3f}, p={p:.4f}") print("\n=== 全図生成完了 ===") for f in [out1, out2, out3, out4]: exists = os.path.exists(f) print(f" {'OK' if exists else 'NG'}: {os.path.basename(f)}") |
保存: html/figures/2020_H4_fig4.png
=== 地域別集計 ===
保健医療費平均 高齢化率平均 消費支出平均 転出率平均
地域
中国・四国 13700.0 33.5 283917.2 16.6
中部 15006.0 31.0 301098.8 14.7
九州・沖縄 14515.8 31.3 276695.1 18.2
北海道・東北 12384.4 33.9 278340.4 15.5
近畿 15016.1 30.1 289630.6 17.6
関東 15719.3 27.9 308303.6 19.4
=== 要約統計 ===
保健医療費 全国平均: 14390 円/世帯
保健医療費 最大: 19107 (愛知県)
保健医療費 最小: 9411 (青森県)
高齢化率 全国平均: 31.4%
高齢化率 最大: 38.6% (秋田県)
R²: 0.575, Adj.R²: 0.535
F統計量: 14.213, p値: 0.0000
高齢化率 vs 保健医療費 r=-0.468, p=0.0009
=== 全図生成完了 ===
OK: 2020_H4_fig1.png
OK: 2020_H4_fig2.png
OK: 2020_H4_fig3.png
OK: 2020_H4_fig4.pngx if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。本研究では、SSDSE-B 2022年断面データ(47都道府県)を用い、保健医療費支出の地域格差を相関分析・OLS重回帰で分析した。主な知見は以下の3点である。
データ出典: 独立行政法人統計センター「SSDSE(社会・人口統計体系データセット)B 都道府県版 2026年版」
分析年度: 2022年度断面データ(n=47都道府県)
使用ツール: Python 3(pandas, numpy, statsmodels, scipy, matplotlib)
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。