このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
自殺は日本において重大な公衆衛生上の課題であり、年間約2万人以上が命を絶っている。 WHOや先行研究は、自殺・精神的健康には社会経済的要因(雇用環境・所得水準・医療アクセス・高齢化等)が深く関与することを指摘している。 本研究は都道府県別データを用いて、死亡率(粗死亡率:健康状態の総合代理指標)と社会経済要因の統計的関係を定量化し、 地域格差を生む構造的要因を明らかにすることを目的とする。
まず「都道府県別自殺死亡率と社会経済要因の関係分析」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。
SSDSE-B Pearson相関 OLS重回帰 地域比較 政策提言
統計数理研究所が提供するSSDSE-B(社会・人口統計体系データセット・都道府県版)2026年版から 2022年度の47都道府県データを使用する。
| 項目 | 内容 |
|---|---|
| データソース | SSDSE-B-2026.csv(統計数理研究所) |
| 対象年度 | 2022年(令和4年)断面データ |
| 観測数 | 47都道府県 |
| 文字コード | CP932(Shift-JIS) |
| 地域コード | R+5桁数字(例:R01000 = 北海道) |
| 種類 | 変数名 | 算出方法 | 平均±SD | 想定効果 |
|---|---|---|---|---|
| 目的変数 | 粗死亡率(千人当たり) | 死亡数 ÷ 総人口 × 1,000 | 13.85 ± 1.92 ‰ | — |
| 説明変数 (社会経済要因) |
求人倍率 | 月間有効求人数 ÷ 月間有効求職者数 | 1.39 ± 0.25 | 雇用環境(正方向) |
| 高齢化率(%) | 65歳以上人口 ÷ 総人口 × 100 | 31.35 ± 3.27 % | 高齢化(正方向) | |
| 保健医療費(円/月) | 二人以上世帯の保健医療費(月額) | 14,390 ± 2,007 円 | 医療アクセス(負方向) | |
| 消費支出(円/月) | 二人以上世帯の消費支出(月額) | 289,630 ± 19,187 円 | 生活水準(負方向) | |
| 合計特殊出生率 | SSDSE-Bの合計特殊出生率 | 1.27 ± 0.12 | 社会活力(負方向) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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) 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() assert len(df) == 47, f"47都道府県のデータが必要です。実際: {len(df)}" |
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) — 列を整数に変換(年度などを数値比較するため)。f"...{x}..." はf-string。文字列の中に {変数} と書くだけで埋め込めて、{x:.2f} のように書式も指定できます。25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | df['死亡率_千人'] = df['死亡数'] / df['総人口'] * 1000 # 説明変数 # 1. 求人倍率(月間有効求人数 / 月間有効求職者数) df['求人倍率'] = df['月間有効求人数(一般)'] / df['月間有効求職者数(一般)'] # 2. 高齢化率(65歳以上人口 / 総人口 × 100) df['高齢化率'] = df['65歳以上人口'] / df['総人口'] * 100 # 3. 保健医療費(二人以上の世帯、円) df['保健医療費'] = df['保健医療費(二人以上の世帯)'] # 4. 消費支出(生活水準の代理) df['消費支出'] = df['消費支出(二人以上の世帯)'] # 5. 離婚率(千人当たり、社会的孤立の代理) df['離婚率_千人'] = df['離婚件数'] / df['総人口'] * 1000 # 6. 出生率(合計特殊出生率)の逆数(社会活力の喪失指標) df['出生率'] = df['合計特殊出生率'] |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。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 71 | region_map = { '北海道': '北海道・東北', '青森県': '北海道・東北', '岩手県': '北海道・東北', '宮城県': '北海道・東北', '秋田県': '北海道・東北', '山形県': '北海道・東北', '福島県': '北海道・東北', '茨城県': '関東', '栃木県': '関東', '群馬県': '関東', '埼玉県': '関東', '千葉県': '関東', '東京都': '関東', '神奈川県': '関東', '新潟県': '中部', '富山県': '中部', '石川県': '中部', '福井県': '中部', '山梨県': '中部', '長野県': '中部', '岐阜県': '中部', '静岡県': '中部', '愛知県': '中部', '三重県': '近畿', '滋賀県': '近畿', '京都府': '近畿', '大阪府': '近畿', '兵庫県': '近畿', '奈良県': '近畿', '和歌山県': '近畿', '鳥取県': '中国・四国', '島根県': '中国・四国', '岡山県': '中国・四国', '広島県': '中国・四国', '山口県': '中国・四国', '徳島県': '中国・四国', '香川県': '中国・四国', '愛媛県': '中国・四国', '高知県': '中国・四国', '福岡県': '九州・沖縄', '佐賀県': '九州・沖縄', '長崎県': '九州・沖縄', '熊本県': '九州・沖縄', '大分県': '九州・沖縄', '宮崎県': '九州・沖縄', '鹿児島県': '九州・沖縄', '沖縄県': '九州・沖縄' } region_colors = { '北海道・東北': '#4e9af1', '関東': '#e05c5c', '中部': '#f0a500', '近畿': '#5cb85c', '中国・四国': '#9b59b6', '九州・沖縄': '#f39c12' } df['地域区分'] = df['都道府県'].map(region_map) df['地域色'] = df['地域区分'].map(region_colors) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。47都道府県の粗死亡率を地域ブロック別に色分けしてランキングした。 死亡率は東北・北海道、中国・四国地方で高く、関東・近畿の大都市圏で低い傾向がある。 この地域格差は高齢化率の地域差と高い相関を示す(r = +0.972)。
都道府県データは47観測値しかないが、地域ブロック別に色分けすることで 空間的パターンが可視化できる。「高い」「低い」だけでなく「どの地域に集中しているか」を 確認することが探索的データ分析(EDA)の第一歩である。
73 74 75 76 77 78 79 80 81 82 83 84 85 | df_sorted = df.sort_values('死亡率_千人', ascending=True).reset_index(drop=True) fig, ax = plt.subplots(figsize=(10, 14)) bars = ax.barh( range(len(df_sorted)), df_sorted['死亡率_千人'], color=df_sorted['地域色'], edgecolor='white', linewidth=0.4, height=0.75 ) ax.set_yticks(range(len(df_sorted))) ax.set_yticklabels(df_sorted['都道府県'], fontsize=8.5) ax.set_xlabel('死亡率(人口千人当たり、2022年)', fontsize=11) ax.set_title('都道府県別 粗死亡率ランキング(2022年)\n目的変数:精神的健康の社会経済的代理指標', fontsize=12, fontweight='bold') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | # 凡例 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, framealpha=0.9) # 全国平均ライン mean_val = df['死亡率_千人'].mean() ax.axvline(mean_val, color='#c0392b', linestyle='--', linewidth=1.2, alpha=0.8) ax.text(mean_val + 0.05, 1.5, f'全国平均\n{mean_val:.1f}‰', color='#c0392b', fontsize=9, va='bottom') ax.set_xlim(0, df_sorted['死亡率_千人'].max() * 1.12) ax.grid(axis='x', alpha=0.3) ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) plt.tight_layout() fig1_path = os.path.join(FIG_DIR, '2021_H5_4_fig1.png') fig.savefig(fig1_path, bbox_inches='tight') plt.close() print(f"\n図1保存: {fig1_path}") |
図1保存: html/figures/2021_H5_4_fig1.png
import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。Pearson相関分析(無相関検定)で関係を確認した後、 6つの社会経済変数を同時に投入したOLS重回帰分析を行い、 各要因の独立した効果(偏回帰係数)を推定した。
| 変数 | 相関係数 r | p値 | 有意性 | 解釈 |
|---|---|---|---|---|
| 高齢化率 | +0.972 | <0.001 | *** | 最強の正の相関:高齢化が死亡率を押し上げる |
| 保健医療費 | -0.554 | <0.001 | *** | 医療支出が多い地域ほど死亡率が低い |
| 消費支出 | -0.447 | 0.0017 | ** | 生活水準が高い地域ほど死亡率が低い |
| 求人倍率 | +0.397 | 0.0058 | ** | 求人が多い地域で死亡率が高い(高齢化と連動) |
| 離婚率 | -0.264 | 0.0728 | ns | 有意な相関なし |
| 合計特殊出生率 | +0.218 | 0.1416 | ns | 有意な相関なし |
| 変数 | 標準化β係数 | p値 | 有意性 | 解釈 |
|---|---|---|---|---|
| 高齢化率 | +1.754 | <0.001 | ** | 最も強い正の効果:高齢化が死亡率を規定 |
| 保健医療費 | -0.139 | 0.131 | ns | 負の効果(非有意:高齢化と交絡) |
| 消費支出 | -0.133 | 0.176 | ns | 負の効果(非有意) |
| 求人倍率 | +0.121 | 0.141 | ns | 正の効果(非有意:高齢化との交絡) |
| 合計特殊出生率 | -0.099 | 0.194 | ns | 負の効果(非有意) |
| 離婚率 | +0.073 | 0.413 | ns | 正の効果(非有意) |
| モデル全体 | R²=0.962, Adj.R²=0.956, F検定 p<0.001 | |||
交絡(Confounding)とは、目的変数と説明変数の両方と相関する第三の変数(交絡変数)が 見かけ上の相関を生み出す現象。本研究では「高齢化率」が典型的な交絡変数として機能している。
例:求人倍率は単変量でr=+0.40(p=0.006)と有意だが、高齢化率を制御すると非有意(p=0.14)になる。 これは「農村部・高齢化地域ほど求人倍率も高い」という地域特性が原因。
106 107 108 109 110 111 | 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, '死亡率_千人'], color=color, s=60, alpha=0.85, zorder=3, label=region) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。112 113 114 115 116 117 | # 都道府県名ラベル for _, row in df.iterrows(): pref = row['都道府県'].replace('県', '').replace('都', '').replace('道', '').replace('府', '') ax.annotate(pref, (row['求人倍率'], row['死亡率_千人']), fontsize=6.5, ha='center', va='bottom', xytext=(0, 3), textcoords='offset points', alpha=0.85) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。for _, row in df.iterrows() — DataFrameを1行ずつ取り出すループ。1点ずつ描画したいときに使用。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | # 回帰線 x_reg = df['求人倍率'].values y_reg = df['死亡率_千人'].values slope, intercept, r_val, p_val, se = 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='#2c3e50', linewidth=1.8, linestyle='-', zorder=2, label=f'回帰線 r={r_val:+.3f}') ax.set_xlabel('求人倍率(月間有効求人数/有効求職者数、2022年)', fontsize=11) ax.set_ylabel('粗死亡率(千人当たり、2022年)', fontsize=11) ax.set_title('求人倍率と死亡率の関係(都道府県別、2022年)\n求人倍率が高い地域ほど死亡率が高い傾向(高齢化率と相関)', fontsize=11, fontweight='bold') ax.legend(loc='upper left', fontsize=9, framealpha=0.9) ax.text(0.98, 0.04, f'r = {r_val:+.3f}, p = {p_val:.4f}', transform=ax.transAxes, ha='right', va='bottom', fontsize=10, bbox=dict(boxstyle='round,pad=0.4', facecolor='#fff9c4', edgecolor='#f9a825', alpha=0.9)) ax.grid(alpha=0.3) ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) plt.tight_layout() fig2_path = os.path.join(FIG_DIR, '2021_H5_4_fig2.png') fig.savefig(fig2_path, bbox_inches='tight') plt.close() print(f"図2保存: {fig2_path}") |
図2保存: html/figures/2021_H5_4_fig2.png
stats.linregress(x, y) — 単回帰の傾き・切片・r値・p値・標準誤差を返します。使わない値は _ で受け取り。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。単変量レベルでは求人倍率と死亡率に有意な正の相関(r=+0.397、p=0.006)が認められた。 ただしこの関係は高齢化率の交絡効果を含むため、以下の散布図で詳細を観察する。
| 地域ブロック | 求人倍率の傾向 | 死亡率の傾向 | 主な要因 |
|---|---|---|---|
| 北海道・東北 | 中程度〜高め | 高い | 高齢化率が高く、医療アクセスが不均等 |
| 中国・四国 | 高め(1.5〜1.9) | 高い | 過疎化と高齢化が同時進行 |
| 関東 | 低め(0.9〜1.5) | 低い | 若年層集積・医療インフラの充実 |
| 近畿 | 低め(1.1〜1.5) | 低〜中程度 | 大都市圏の人口構造 |
| 九州・沖縄 | 中程度〜高め | 中程度 | 沖縄の低高齢化率が引き下げ |
求人倍率は単変量で「正の相関(r=+0.40)」を示したが、 これは直感に反して「求人が多い地域ほど死亡率が高い」と読める。 実際は「地方・農村部ほど求人倍率が高く(都市競争がない)、かつ高齢化も進む」という 第三の変数(高齢化)が生み出す見かけの相関である。
この現象はシンプソンのパラドックスや生態学的誤謬(ecological fallacy)と関連し、 集計データの分析では常に交絡変数の存在を意識する必要がある。
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 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 | var_labels = { '死亡率_千人': '死亡率\n(千人当たり)', '求人倍率': '求人倍率', '高齢化率': '高齢化率\n(%)', '保健医療費': '保健医療費\n(円/月)', '消費支出': '消費支出\n(円/月)', '離婚率_千人': '離婚率\n(千人当たり)', '出生率': '合計特殊\n出生率' } corr_cols = list(var_labels.keys()) corr_matrix = df[corr_cols].corr() fig, ax = plt.subplots(figsize=(9, 7)) n = len(corr_cols) labels = [var_labels[c] for c in corr_cols] 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.8, label='Pearson 相関係数') ax.set_xticks(range(n)) ax.set_yticks(range(n)) ax.set_xticklabels(labels, fontsize=9, rotation=0, ha='center') ax.set_yticklabels(labels, fontsize=9) for i in range(n): for j in range(n): val = corr_matrix.values[i, j] txt_color = 'white' if abs(val) > 0.6 else 'black' ax.text(j, i, f'{val:.2f}', ha='center', va='center', fontsize=9, color=txt_color, fontweight='bold' if abs(val) > 0.5 else 'normal') ax.set_title('社会経済変数の相関行列(Pearson相関係数、2022年、47都道府県)', fontsize=11, fontweight='bold', pad=15) ax.spines[:].set_visible(False) plt.tight_layout() fig3_path = os.path.join(FIG_DIR, '2021_H5_4_fig3.png') fig.savefig(fig3_path, bbox_inches='tight') plt.close() print(f"図3保存: {fig3_path}") |
図3保存: html/figures/2021_H5_4_fig3.png
import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。分析結果は、高齢化率が死亡率の最大の規定要因(β=+1.754、p<0.001)であることを示した。 一方、保健医療費の充実(単変量 r=-0.554)と生活水準(消費支出 r=-0.447)が 死亡率を低減する方向に作用している。これらの知見から以下の政策的示唆が得られる。
| 課題 | 統計的根拠 | 政策オプション |
|---|---|---|
| 地方圏の高死亡率 | 高齢化率との相関 r=+0.972 | 高齢者の生活支援・在宅ケア体制の強化、地方移住促進で若年人口維持 |
| 医療アクセスの格差 | 保健医療費との相関 r=-0.554 | 農村部・離島での医療施設整備、遠隔医療(テレヘルス)の普及 |
| 精神的健康への取り組み | 社会経済的脆弱性と健康格差の連動 | 精神科医療へのアクセス向上、自殺予防相談窓口の地域展開 |
| 生活水準の向上 | 消費支出との相関 r=-0.447 | 最低賃金の改善、社会保障給付の充実による格差是正 |
重回帰分析では説明変数が多いほど過学習のリスクが高まる。 本研究のようにN=47(少数)でK=6(説明変数)の場合、 自由度が小さく推定が不安定になりやすい。変数選択の方法として p値基準(バックワード法)とAIC最小化の二つが代表的。
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | print("=" * 60) print("相関分析(目的変数: 死亡率 千人当たり)") print("=" * 60) explan_vars = { '求人倍率': '求人倍率', '高齢化率': '高齢化率', '保健医療費': '保健医療費', '消費支出': '消費支出', '離婚率_千人': '離婚率_千人', '出生率': '出生率' } corr_results = {} for varname, col in explan_vars.items(): r, p = stats.pearsonr(df[col], df['死亡率_千人']) corr_results[varname] = {'r': r, 'p': p} sig = '*' if p < 0.05 else ' ' print(f" {varname:10s}: r={r:+.4f}, p={p:.4f} {sig}") |
============================================================ 相関分析(目的変数: 死亡率 千人当たり) ============================================================ 求人倍率 : r=+0.3968, p=0.0058 * 高齢化率 : r=+0.9722, p=0.0000 * 保健医療費 : r=-0.5540, p=0.0001 * 消費支出 : r=-0.4466, p=0.0017 * 離婚率_千人 : r=-0.2641, p=0.0728 出生率 : r=+0.2177, p=0.1416
stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。202 203 204 205 206 207 | print() print("=" * 60) print("重回帰分析(OLS)") print("=" * 60) X_vars = ['求人倍率', '高齢化率', '保健医療費', '消費支出', '離婚率_千人', '出生率'] X = df[X_vars].copy() |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。208 209 210 211 212 213 214 215 | # 標準化(標準化偏回帰係数用) X_std = (X - X.mean()) / X.std() y = df['死亡率_千人'] # モデル推定(非標準化) X_const = sm.add_constant(X) model = sm.OLS(y, X_const).fit() print(model.summary()) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。sm.add_constant(X) — 切片項(定数1の列)を先頭に追加。statsmodelsで必須。sm.OLS(y, X).fit() — 最小二乗法でモデルを推定。model.params, model.pvalues, model.conf_int() で結果取得。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。216 217 218 219 220 221 222 223 224 225 226 | # 標準化モデル X_std_const = sm.add_constant(X_std) model_std = sm.OLS(y, X_std_const).fit() print() print("標準化偏回帰係数:") for v, coef, p in zip(X_vars, model_std.params[1:], model_std.pvalues[1:]): sig = '**' if p < 0.01 else ('*' if p < 0.05 else '') print(f" {v:12s}: β={coef:+.4f}, p={p:.4f} {sig}") print(f" R² = {model_std.rsquared:.4f}") print(f" Adj.R² = {model_std.rsquared_adj:.4f}") |
============================================================
重回帰分析(OLS)
============================================================
OLS Regression Results
==============================================================================
Dep. Variable: 死亡率_千人 R-squared: 0.962
Model: OLS Adj. R-squared: 0.956
Method: Least Squares F-statistic: 168.1
Date: Mon, 18 May 2026 Prob (F-statistic): 9.11e-27
Time: 11:23:51 Log-Likelihood: -20.136
No. Observations: 47 AIC: 54.27
Df Residuals: 40 BIC: 67.22
Df Model: 6
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const -0.3290 2.147 -0.153 0.879 -4.669 4.011
求人倍率 0.4885 0.325 1.503 0.141 -0.169 1.146
高齢化率 0.5366 0.024 21.990 0.000 0.487 0.586
保健医療費 -6.915e-05 4.49e-05 -1.540 0.131 -0.000 2.16e-05
消費支出 -6.912e-06 5.01e-06 -1.379 0.176 -1.7e-05 3.22e-06
離婚率_千人 0.4071 0.492 0.828 0.413 -0.586 1.401
出生率 -0.6638 0.503 -1.321 0.194 -1.680 0.352
==============================================================================
Omnibus: 0.180 Durbin-Watson: 2.094
Prob(Omnibus): 0.914 Jarque-Bera (JB): 0.074
Skew: 0.090 Prob(JB): 0.964
Kurtosis: 2.930 Cond. No. 1.08e+07
==============================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 1.08e+07. This might indicate that there are
strong multicollinearity or other numerical problems.
標準化偏回帰係数:
求人倍率 : β=+0.1208, p=0.1408
高齢化率 : β=+1.7544, p=0.0000 **
保健医療費 : β=-0.1388, p=0.1314
消費支出 : β=-0.1326, p=0.1755
離婚率_千人 : β=+0.0728, p=0.4125
出生率 : β=-0.0992, p=0.1941
R² = 0.9619
Adj.R² = 0.9561sm.add_constant(X) — 切片項(定数1の列)を先頭に追加。statsmodelsで必須。sm.OLS(y, X).fit() — 最小二乗法でモデルを推定。model.params, model.pvalues, model.conf_int() で結果取得。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。227 228 229 230 231 232 233 | std_coefs = model_std.params[1:].values std_pvals = model_std.pvalues[1:].values std_conf = model_std.conf_int().iloc[1:].values # [lower, upper] # エラーバー(95%CI) err_lower = std_coefs - std_conf[:, 0] err_upper = std_conf[:, 1] - std_coefs |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。234 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 | # 変数名(表示用) var_display = ['求人倍率', '高齢化率', '保健医療費\n(円/月)', '消費支出\n(円/月)', '離婚率\n(千人当たり)', '合計特殊\n出生率'] # 係数の絶対値でソート(大きい順) sort_idx = np.argsort(np.abs(std_coefs)) coefs_s = std_coefs[sort_idx] pvals_s = std_pvals[sort_idx] labels_s = [var_display[i] for i in sort_idx] err_lo_s = err_lower[sort_idx] err_hi_s = err_upper[sort_idx] colors_bar = ['#c0392b' if p < 0.05 else '#95a5a6' for p in pvals_s] fig, ax = plt.subplots(figsize=(9, 5)) bars = ax.barh(range(len(coefs_s)), coefs_s, color=colors_bar, height=0.6, edgecolor='white', linewidth=0.5) ax.errorbar(coefs_s, range(len(coefs_s)), xerr=[err_lo_s, err_hi_s], fmt='none', color='#2c3e50', capsize=4, linewidth=1.2) ax.axvline(0, color='#2c3e50', linewidth=1.0, linestyle='--', alpha=0.6) ax.set_yticks(range(len(labels_s))) ax.set_yticklabels(labels_s, fontsize=10) ax.set_xlabel('標準化偏回帰係数(β)', fontsize=11) ax.set_title(f'重回帰分析:標準化偏回帰係数(95%信頼区間)\n目的変数: 粗死亡率(千人当たり)、R²={model_std.rsquared:.3f}', fontsize=11, fontweight='bold') from matplotlib.patches import Patch legend_elems = [ Patch(facecolor='#c0392b', label='有意(p<0.05)'), Patch(facecolor='#95a5a6', label='非有意(p≥0.05)') ] ax.legend(handles=legend_elems, loc='lower right', fontsize=9) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。{値:.2f}(小数2桁)、{値:,}(3桁区切り)、{値:>10}(右寄せ10桁)など、覚えると出力が一気に整います。267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | # p値をバーの横に表示 for i, (c, p) in enumerate(zip(coefs_s, pvals_s)): sign = '**' if p < 0.01 else ('*' if p < 0.05 else 'ns') offset = 0.02 if c >= 0 else -0.02 ha = 'left' if c >= 0 else 'right' ax.text(c + offset, i, sign, ha=ha, va='center', fontsize=9, color='#2c3e50', fontweight='bold') ax.grid(axis='x', alpha=0.3) ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) plt.tight_layout() fig4_path = os.path.join(FIG_DIR, '2021_H5_4_fig4.png') fig.savefig(fig4_path, bbox_inches='tight') plt.close() print(f"図4保存: {fig4_path}") |
図4保存: html/figures/2021_H5_4_fig4.png
fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。plt.subplots(figsize=(W, H)) で図サイズ指定、fig.savefig(..., bbox_inches='tight') で余白を自動で詰めて保存。283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 | print() print("=" * 60) print("統計サマリー(HTML作成用)") print("=" * 60) print(f"分析対象: 47都道府県(2022年度)") print(f"目的変数: 粗死亡率(千人当たり)") print(f" 平均: {df['死亡率_千人'].mean():.2f}‰") print(f" 標準偏差: {df['死亡率_千人'].std():.2f}‰") print(f" 最大: {df.loc[df['死亡率_千人'].idxmax(), '都道府県']} {df['死亡率_千人'].max():.2f}‰") print(f" 最小: {df.loc[df['死亡率_千人'].idxmin(), '都道府県']} {df['死亡率_千人'].min():.2f}‰") print() print("相関分析:") for k, v in corr_results.items(): print(f" {k}: r={v['r']:+.4f}, p={v['p']:.4f}") print() print(f"重回帰分析: R²={model_std.rsquared:.4f}, Adj.R²={model_std.rsquared_adj:.4f}") print("標準化偏回帰係数:") for v, coef, pval in zip(X_vars, model_std.params[1:], model_std.pvalues[1:]): sig = '**' if pval < 0.01 else ('*' if pval < 0.05 else 'ns') print(f" {v}: β={coef:+.4f}, p={pval:.4f} {sig}") print() print("完了") |
============================================================ 統計サマリー(HTML作成用) ============================================================ 分析対象: 47都道府県(2022年度) 目的変数: 粗死亡率(千人当たり) 平均: 13.85‰ 標準偏差: 1.92‰ 最大: 秋田県 18.55‰ 最小: 東京都 9.92‰ 相関分析: 求人倍率: r=+0.3968, p=0.0058 高齢化率: r=+0.9722, p=0.0000 保健医療費: r=-0.5540, p=0.0001 消費支出: r=-0.4466, p=0.0017 離婚率_千人: r=-0.2641, p=0.0728 出生率: r=+0.2177, p=0.1416 重回帰分析: R²=0.9619, Adj.R²=0.9561 標準化偏回帰係数: 求人倍率: β=+0.1208, p=0.1408 ns 高齢化率: β=+1.7544, p=0.0000 ** 保健医療費: β=-0.1388, p=0.1314 ns 消費支出: β=-0.1326, p=0.1755 ns 離婚率_千人: β=+0.0728, p=0.4125 ns 出生率: β=-0.0992, p=0.1941 ns 完了
{値:.2f}(小数2桁)、{値:,}(3桁区切り)、{値:>10}(右寄せ10桁)など、覚えると出力が一気に整います。SSDSE-B(2022年、47都道府県)のデータを用いた相関分析・重回帰分析の結果、以下の知見が得られた:
| データ | 出典 |
|---|---|
| SSDSE-B-2026(都道府県別統計データ) | 統計数理研究所 SSDSE(社会・人口統計体系) |
| 死亡数・総人口・高齢化率 | 総務省統計局 住民基本台帳人口移動報告 / 人口動態統計 |
| 求人・求職データ | 厚生労働省 一般職業紹介状況 |
| 消費支出・保健医療費 | 総務省 家計調査 |
本教育用コードはSSDSE-B-2026.csvの実データを使用(合成データなし)。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。