このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
「ソーシャルキャピタル(社会関係資本)」とは、人々の間の信頼・互酬性・ネットワークを指す概念であり、地域コミュニティの活力と深く結びついている。Robert Putnam(2000)は、ソーシャルキャピタルが高い地域ほど行政サービスの質が高く、犯罪率が低く、健康水準が高いことを示した。
まず「ソーシャルキャピタルと地域コミュニティ活動の関係分析」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。
日本では少子高齢化・人口流出が進み、地域コミュニティの維持が政策的急務となっている。コミュニティ活動の豊かさは、子育て支援・高齢者福祉・環境保全などの行政サービスと相互に作用する。本研究は、SSDSE-B(都道府県統計)を用いて、保育所密度・医療施設密度・リサイクル率・教育投資などをソーシャルキャピタルのプロキシ変数として設定し、それらが合計特殊出生率(地域の持続可能性の代理)に与える影響を定量的に分析した。
ソーシャルキャピタル SSDSE-B 2022年度 プロキシ変数 47都道府県
「ソーシャルキャピタル」は調査票なしに都道府県統計から直接は得られない。そのためプロキシ変数(代理変数)を使う。適切なプロキシは:
| データ項目 | 変数名 | 変数の意味・役割 | カテゴリ |
|---|---|---|---|
| 保育所等数 / 人口 1 万人 | 保育所密度 | 子育て支援・ファミリーコミュニティの指標 | ソーシャルキャピタル |
| 65 歳以上人口割合 | 高齢化率 (%) | 高齢者コミュニティ・地域構造の指標 | ソーシャルキャピタル |
| ごみのリサイクル率 | リサイクル率 (%) | 住民の協力意識・環境コミュニティ | ソーシャルキャピタル |
| 高校卒業者のうち進学者割合 | 進学率 (%) | 教育志向・将来投資の強さ | コミュニティ活動 |
| 婚姻件数 / 人口千人 | 婚姻率 | 家族形成・社会的紐帯の強さ | コミュニティ活動 |
| 教養娯楽費 / 消費支出 | 教養娯楽費率 (%) | 文化活動・余暇コミュニティへの参加 | コミュニティ活動 |
| (病院数 + 診療所数) / 万人 | 医療施設密度 | 地域医療コミュニティの充実度 | コミュニティ基盤 |
| 合計特殊出生率 | 合計特殊出生率 | 地域の持続可能性・幸福度の代理【目的変数】 | 目的変数 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | region_map = { '北海道': '北海道・東北', '青森県': '北海道・東北', '岩手県': '北海道・東北', '宮城県': '北海道・東北', '秋田県': '北海道・東北', '山形県': '北海道・東北', '福島県': '北海道・東北', '茨城県': '関東', '栃木県': '関東', '群馬県': '関東', '埼玉県': '関東', '千葉県': '関東', '東京都': '関東', '神奈川県': '関東', '新潟県': '中部', '富山県': '中部', '石川県': '中部', '福井県': '中部', '山梨県': '中部', '長野県': '中部', '岐阜県': '中部', '静岡県': '中部', '愛知県': '中部', '三重県': '近畿', '滋賀県': '近畿', '京都府': '近畿', '大阪府': '近畿', '兵庫県': '近畿', '奈良県': '近畿', '和歌山県': '近畿', '鳥取県': '中国・四国', '島根県': '中国・四国', '岡山県': '中国・四国', '広島県': '中国・四国', '山口県': '中国・四国', '徳島県': '中国・四国', '香川県': '中国・四国', '愛媛県': '中国・四国', '高知県': '中国・四国', '福岡県': '九州・沖縄', '佐賀県': '九州・沖縄', '長崎県': '九州・沖縄', '熊本県': '九州・沖縄', '大分県': '九州・沖縄', '宮崎県': '九州・沖縄', '鹿児島県': '九州・沖縄', '沖縄県': '九州・沖縄' } region_colors = { '北海道・東北': '#4e9af1', '関東': '#e05c5c', '中部': '#f0a500', '近畿': '#5cb85c', '中国・四国': '#9b59b6', '九州・沖縄': '#f39c12' } df['地域'] = df['都道府県'].map(region_map) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。23 24 25 26 27 28 29 | pop = df['総人口'] # 単位: 人 # 保育所密度(保育所等数 / 総人口 × 10,000) df['保育所密度'] = df['保育所等数'] / pop * 10000 # 高齢化率(65歳以上 / 総人口) df['高齢化率'] = df['65歳以上人口'] / pop * 100 |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。30 31 32 33 34 35 36 37 | # 年少人口率(15歳未満 / 総人口) df['年少人口率'] = df['15歳未満人口'] / pop * 100 # 医療施設密度(一般病院数 + 診療所数 / 万人) df['医療施設密度'] = (df['一般病院数'] + df['一般診療所数']) / pop * 10000 # リサイクル率(環境への意識 = ソーシャルキャピタルの代理) df['リサイクル率'] = df['ごみのリサイクル率'] |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。38 39 40 41 42 43 44 45 | # 教育進学率(高校卒業→進学率) df['進学率'] = df['高等学校卒業者のうち進学者数'] / df['高等学校卒業者数'] * 100 # 婚姻率(人口千人あたり) df['婚姻率'] = df['婚姻件数'] / pop * 1000 # 消費支出に占める教養娯楽費率(文化活動への関与) df['教養娯楽費率'] = df['教養娯楽費(二人以上の世帯)'] / df['消費支出(二人以上の世帯)'] * 100 |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。46 47 48 49 50 51 52 53 | # 消費支出に占める教育費率 df['教育費率'] = df['教育費(二人以上の世帯)'] / df['消費支出(二人以上の世帯)'] * 100 # 旅行・観光活動(延べ宿泊者 / 万人) df['観光密度'] = df['延べ宿泊者数'] / pop * 10000 # 保育所定員充足率(在所児 / 定員) df['保育充足率'] = df['保育所等在所児数'] / df['保育所等定員数'] * 100 |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。47 都道府県の保育所密度(人口 1 万人あたりの保育所等数)と合計特殊出生率の関係を地域色で可視化した。回帰直線は明確な正の傾きを示し、相関係数 r = 0.628(p < 0.0001)と統計的に有意な正の相関が確認された。
8 変数間の Pearson 相関行列をヒートマップで示す。赤色が正の相関、青色が負の相関を表す。
| 変数ペア | 相関係数 r | p 値 | 解釈 |
|---|---|---|---|
| 高齢化率 ↔ 婚姻率 | -0.890** | <0.001 | 高齢化が進む地域ほど婚姻率が低い(強い負の相関) |
| 進学率 ↔ 教養娯楽費率 | +0.627** | <0.001 | 教育投資が高い地域は文化活動も活発 |
| 高齢化率 ↔ 進学率 | -0.588** | <0.001 | 若者が多い地域ほど進学率が高い |
| 保育所密度 ↔ 進学率 | -0.569** | <0.001 | 保育所が多い地域(地方)は進学率が低い傾向 |
| 保育所密度 ↔ 教養娯楽費率 | -0.519** | <0.001 | 都市部は教養娯楽費率が高く保育所密度が低い |
| 進学率 ↔ 婚姻率 | +0.555** | <0.001 | 教育投資と家族形成の正の関係 |
**: p < 0.01(両側検定)
相関行列から「高齢化率と婚姻率(r = -0.890)」のように強く相関する変数が複数存在する。これらを同時に重回帰モデルに投入すると多重共線性が生じ、回帰係数の推定が不安定になる。
55 56 57 58 59 60 | fig, ax = plt.subplots(figsize=(9, 6.5)) for region, grp in df_ana.groupby('地域'): color = region_colors[region] ax.scatter(grp['保育所密度'], grp['合計特殊出生率'], color=color, s=60, alpha=0.85, label=region, zorder=3) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df.groupby('列').apply(関数) — グループごとに関数を適用。時系列や地域別の集計でよく使います。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。61 62 63 64 65 66 | # ラベル for _, row in df_ana.iterrows(): ax.annotate(row['都道府県'], xy=(row['保育所密度'], row['合計特殊出生率']), fontsize=6.5, ha='left', va='bottom', xytext=(2, 2), textcoords='offset points', color='#333333') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。for _, row in df.iterrows() — DataFrameを1行ずつ取り出すループ。1点ずつ描画したいときに使用。np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。67 68 69 70 71 72 73 74 75 | # 回帰線 x_fit = np.linspace(df_ana['保育所密度'].min(), df_ana['保育所密度'].max(), 200) slope, intercept, r_val, p_val, se = stats.linregress(df_ana['保育所密度'], df_ana['合計特殊出生率']) y_fit = slope * x_fit + intercept ax.plot(x_fit, y_fit, color='#333333', linewidth=1.5, linestyle='--', zorder=2) ax.set_xlabel('保育所密度(保育所等数 / 人口1万人)', fontsize=12) ax.set_ylabel('合計特殊出生率', fontsize=12) ax.set_title('図1: 保育所密度と合計特殊出生率の関係(2022年度, 47都道府県)', fontsize=13, pad=12) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。stats.linregress(x, y) — 単回帰の傾き・切片・r値・p値・標準誤差を返します。使わない値は _ で受け取り。{値:.2f}(小数2桁)、{値:,}(3桁区切り)、{値:>10}(右寄せ10桁)など、覚えると出力が一気に整います。76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | # 凡例 handles, labels = ax.get_legend_handles_labels() ax.legend(handles, labels, loc='upper right', fontsize=9, framealpha=0.9) # 相関係数注記 ax.text(0.03, 0.97, f'r = {r_val:.3f} (p = {p_val:.4f})', transform=ax.transAxes, fontsize=10, va='top', ha='left', bbox=dict(boxstyle='round,pad=0.4', fc='white', ec='#aaaaaa', alpha=0.9)) ax.grid(True, alpha=0.3) plt.tight_layout() fig.savefig(os.path.join(FIG_DIR, '2021_U5_5_fig1.png'), bbox_inches='tight') plt.close(fig) print("fig1 saved") |
fig1 saved
fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。plt.subplots(figsize=(W, H)) で図サイズ指定、fig.savefig(..., bbox_inches='tight') で余白を自動で詰めて保存。合計特殊出生率を目的変数 (Y)、7 つのプロキシ変数を説明変数として、標準化 OLS 重回帰分析を実施した。すべての変数を標準化(平均 0、標準偏差 1)してから投入することで、単位が異なる変数の影響力を比較可能にした。
R² = 0.549 は、7 変数で合計特殊出生率の分散の約 55% を説明できることを示す。F 検定は p < 0.001 と有意であり、モデル全体として出生率に対する説明力が認められた。
| 変数 | β(標準化) | 95% CI | p 値 | 有意性 | 解釈 |
|---|---|---|---|---|---|
| 保育所密度 | +0.062 | [0.021, 0.102] | 0.004 | * | 保育所が多い地域ほど出生率が高い |
| 医療施設密度 | +0.053 | [0.002, 0.104] | 0.042 | * | 医療充実が子育て安心感を高める |
| 高齢化率 | -0.052 | [-0.164, 0.059] | 0.350 | n.s. | 他変数を制御すると有意差消える |
| 進学率 | -0.046 | [-0.100, 0.009] | 0.099 | n.s. | 高進学率地域は出産が後回しになる傾向 |
| 教養娯楽費率 | -0.028 | [-0.073, 0.016] | 0.204 | n.s. | 都市型消費が多い地域は出生率低め |
| リサイクル率 | +0.017 | [-0.021, 0.056] | 0.375 | n.s. | 単独では有意でない |
| 婚姻率 | -0.016 | [-0.119, 0.088] | 0.763 | n.s. | 高齢化率との多重共線性の影響 |
*: p < 0.05(両側検定)。n.s. = 非有意。標準化偏回帰係数は各変数を標準化後に推定。
単位が異なる変数(保育所密度=箇所/万人、高齢化率=%)をそのまま比較しても意味がない。変数を標準化(z スコア化)してから回帰すれば、係数 β が「説明変数が 1 標準偏差変化したとき、目的変数が何標準偏差変化するか」を示す共通単位になる。
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | fig, ax = plt.subplots(figsize=(9, 7.5)) n = len(sc_vars) im = ax.imshow(corr_matrix.values, cmap='RdBu_r', vmin=-1, vmax=1, aspect='auto') plt.colorbar(im, ax=ax, shrink=0.8, label='Pearson r') ax.set_xticks(range(n)) ax.set_yticks(range(n)) ax.set_xticklabels(corr_labels, rotation=40, ha='right', fontsize=10) ax.set_yticklabels(corr_labels, fontsize=10) for i in range(n): for j in range(n): val = corr_matrix.values[i, j] text_color = 'white' if abs(val) > 0.6 else 'black' ax.text(j, i, f'{val:.2f}', ha='center', va='center', fontsize=9, color=text_color, fontweight='bold') ax.set_title('図2: ソーシャルキャピタル関連変数のPearson相関行列(2022年度)', fontsize=12, pad=12) plt.tight_layout() fig.savefig(os.path.join(FIG_DIR, '2021_U5_5_fig2.png'), bbox_inches='tight') plt.close(fig) print("fig2 saved") |
fig2 saved
fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。Ward 法階層クラスタリングを用いて、コミュニティ特性が似ている都道府県をグループ化した。使用変数は「保育所密度・高齢化率・リサイクル率・婚姻率・医療施設密度・進学率」の 6 変数(すべて標準化)。
青森・岩手・秋田・山形・島根・高知・佐賀・長崎・熊本・大分・宮崎・鹿児島など
特徴:高齢化率が高く、婚姻率が低め。保育所密度は中程度。地方農村型コミュニティ。
埼玉・千葉・東京・神奈川・愛知・沖縄
特徴:進学率・教養娯楽費率が高く、保育所密度が低い。出生率は全般的に低め。大都市圏型。
北海道・茨城・富山・長野・三重・鳥取・岡山・広島・山口・香川・福岡など
特徴:各指標がバランスよく中程度。医療施設密度がやや高い。
宮城・福島・栃木・群馬・石川・福井・山梨・岐阜・静岡・滋賀・京都・大阪・兵庫・奈良・和歌山・愛媛・徳島など
特徴:高齢化率が低く、婚姻率・進学率が高い。都市近郊・中規模都市に多い。
Ward 法では、2 つのクラスターを統合したとき「クラスター内の分散の増加量」が最小になる組み合わせを逐次的に選ぶ。データは事前に標準化する(スケールに左右されないため)。
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | labels_jp = { '保育所密度': '保育所密度\n(保育所等数/万人)', '高齢化率': '高齢化率', 'リサイクル率': 'リサイクル率\n(環境意識)', '進学率': '進学率\n(教育志向)', '婚姻率': '婚姻率', '教養娯楽費率': '教養娯楽費率\n(文化活動)', '医療施設密度': '医療施設密度', } order = coef.abs().sort_values(ascending=True).index coef_sorted = coef[order] ci_sorted = ci.loc[order] pval_sorted = pval[order] ylabels = [labels_jp.get(v, v) for v in order] colors_bar = ['#e05c5c' if p < 0.05 else '#aec6e8' for p in pval_sorted] fig, ax = plt.subplots(figsize=(9, 5.5)) y_pos = np.arange(len(order)) bars = ax.barh(y_pos, coef_sorted.values, color=colors_bar, height=0.55, zorder=3) ax.errorbar(coef_sorted.values, y_pos, xerr=np.array([(coef_sorted.values - ci_sorted.iloc[:, 0].values), (ci_sorted.iloc[:, 1].values - coef_sorted.values)]), fmt='none', color='#333333', linewidth=1.3, capsize=4, zorder=4) ax.axvline(0, color='black', linewidth=1.0, zorder=2) ax.set_yticks(y_pos) ax.set_yticklabels(ylabels, fontsize=10) ax.set_xlabel('標準化偏回帰係数(β)', fontsize=11) ax.set_title(f'図3: 標準化偏回帰係数と95%信頼区間\n(目的変数: 合計特殊出生率, R²={r2:.3f})', fontsize=12, pad=10) from matplotlib.patches import Patch legend_elements = [ Patch(facecolor='#e05c5c', label='有意 (p < 0.05)'), Patch(facecolor='#aec6e8', label='非有意 (p >= 0.05)') ] ax.legend(handles=legend_elements, loc='lower right', fontsize=10) ax.grid(True, axis='x', alpha=0.35) plt.tight_layout() fig.savefig(os.path.join(FIG_DIR, '2021_U5_5_fig3.png'), bbox_inches='tight') plt.close(fig) print("fig3 saved") |
fig3 saved
import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。{値:.2f}(小数2桁)、{値:,}(3桁区切り)、{値:>10}(右寄せ10桁)など、覚えると出力が一気に整います。本分析の結果から、以下の政策的な示唆が得られた。
| クラスター | 代表地域 | 主な課題 | 政策的アプローチ |
|---|---|---|---|
| クラスター 1 地方高齢型 |
東北・九州農村 | 高齢化・若者流出・婚姻率低下 | 若者定着支援、保育所整備、移住促進 |
| クラスター 2 都市型 |
首都圏・名古屋 | 待機児童・住居費高騰・低出生率 | 保育所拡充・育休制度強化・住居支援 |
| クラスター 3 バランス型 |
北海道・中国地方 | 医療過疎・雇用多様性不足 | 医療コミュニティ強化・産業誘致 |
| クラスター 4 若年活性型 |
都市近郊・中規模都市 | 持続的なコミュニティ維持 | 教育投資継続・文化活動支援 |
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | 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 from sklearn.preprocessing import StandardScaler from scipy.cluster.hierarchy import dendrogram, linkage from scipy.spatial.distance import pdist 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) |
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) — 列を整数に変換(年度などを数値比較するため)。StandardScaler().fit_transform(X) — 各列を「平均0・分散1」に標準化。単位が違う変数のβを比較可能に。f"...{x}..." はf-string。文字列の中に {変数} と書くだけで埋め込めて、{x:.2f} のように書式も指定できます。186 187 188 | # 2022年度断面データ df = df_b[df_b['年度'] == 2022].copy().reset_index(drop=True) assert len(df) == 47, f"47都道府県が揃っていません: {len(df)}件" |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。189 190 191 192 193 194 195 | vars_all = [ '合計特殊出生率', '保育所密度', '高齢化率', '年少人口率', '医療施設密度', 'リサイクル率', '進学率', '婚姻率', '教養娯楽費率', '教育費率', '観光密度', '保育充足率' ] df_ana = df[['都道府県', '地域'] + vars_all].dropna().copy() print(f"分析対象: {len(df_ana)}都道府県") |
分析対象: 47都道府県
[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。196 197 198 199 200 201 202 203 204 | sc_vars = [ '保育所密度', '高齢化率', 'リサイクル率', '進学率', '婚姻率', '教養娯楽費率', '教育費率', '医療施設密度' ] corr_labels = [ '保育所密度', '高齢化率', 'リサイクル率', '進学率', '婚姻率', '教養娯楽費率', '教育費率', '医療施設密度' ] corr_matrix = df_ana[sc_vars].corr() |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。205 206 207 208 209 210 | y_var = '合計特殊出生率' x_vars = ['保育所密度', '高齢化率', 'リサイクル率', '進学率', '婚姻率', '教養娯楽費率', '医療施設密度'] y = df_ana[y_var] X_raw = df_ana[x_vars] |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。211 212 213 214 215 216 217 218 | # 標準化 scaler = StandardScaler() X_std = scaler.fit_transform(X_raw) X_std_df = pd.DataFrame(X_std, columns=x_vars, index=df_ana.index) X_std_df = sm.add_constant(X_std_df) ols_model = sm.OLS(y, X_std_df).fit() print(ols_model.summary()) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。StandardScaler().fit_transform(X) — 各列を「平均0・分散1」に標準化。単位が違う変数のβを比較可能に。sm.add_constant(X) — 切片項(定数1の列)を先頭に追加。statsmodelsで必須。sm.OLS(y, X).fit() — 最小二乗法でモデルを推定。model.params, model.pvalues, model.conf_int() で結果取得。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。219 220 221 222 223 224 225 226 227 228 229 230 | # 標準化偏回帰係数と95%CI coef = ols_model.params[1:] # 定数項を除く ci = ols_model.conf_int().iloc[1:] pval = ols_model.pvalues[1:] r2 = ols_model.rsquared r2_adj = ols_model.rsquared_adj f_stat = ols_model.fvalue f_pval = ols_model.f_pvalue print(f"\nR² = {r2:.3f}, Adj R² = {r2_adj:.3f}") print(f"F統計量 = {f_stat:.2f}, p値 = {f_pval:.4f}") |
OLS Regression Results
==============================================================================
Dep. Variable: 合計特殊出生率 R-squared: 0.549
Model: OLS Adj. R-squared: 0.468
Method: Least Squares F-statistic: 6.783
Date: Mon, 18 May 2026 Prob (F-statistic): 2.78e-05
Time: 11:24:00 Log-Likelihood: 41.894
No. Observations: 47 AIC: -67.79
Df Residuals: 39 BIC: -52.99
Df Model: 7
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const 1.3583 0.016 85.482 0.000 1.326 1.390
保育所密度 0.0615 0.020 3.047 0.004 0.021 0.102
高齢化率 -0.0522 0.055 -0.946 0.350 -0.164 0.059
リサイクル率 0.0171 0.019 0.898 0.375 -0.021 0.056
進学率 -0.0456 0.027 -1.691 0.099 -0.100 0.009
婚姻率 -0.0155 0.051 -0.304 0.763 -0.119 0.088
教養娯楽費率 -0.0283 0.022 -1.292 0.204 -0.073 0.016
医療施設密度 0.0528 0.025 2.105 0.042 0.002 0.104
==============================================================================
Omnibus: 11.366 Durbin-Watson: 0.934
Prob(Omnibus): 0.003 Jarque-Bera (JB): 11.164
Skew: -1.056 Prob(JB): 0.00376
Kurtosis: 4.115 Cond. No. 8.62
==============================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
R² = 0.549, Adj R² = 0.468
F統計量 = 6.78, p値 = 0.0000s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。231 232 233 234 235 236 237 238 | cluster_vars = ['保育所密度', '高齢化率', 'リサイクル率', '婚姻率', '医療施設密度', '進学率'] X_clust = df_ana[cluster_vars].values X_clust_std = StandardScaler().fit_transform(X_clust) Z = linkage(X_clust_std, method='ward') # 個々の相関係数(fig1用) r_birth_hoiku, p_birth_hoiku = stats.pearsonr(df_ana['保育所密度'], df_ana['合計特殊出生率']) print(f"\n保育所密度 vs 合計特殊出生率: r={r_birth_hoiku:.3f}, p={p_birth_hoiku:.4f}") |
保育所密度 vs 合計特殊出生率: r=0.628, p=0.0000
stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。StandardScaler().fit_transform(X) — 各列を「平均0・分散1」に標準化。単位が違う変数のβを比較可能に。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | fig, ax = plt.subplots(figsize=(14, 6)) pref_names = df_ana['都道府県'].tolist() dn = dendrogram(Z, labels=pref_names, ax=ax, leaf_rotation=90, leaf_font_size=9, color_threshold=Z[-4, 2]) ax.set_title('図4: Ward法による47都道府県のコミュニティ特性クラスタリング(2022年度)', fontsize=13, pad=12) ax.set_ylabel('クラスター間距離(Ward距離)', fontsize=11) ax.set_xlabel('都道府県', fontsize=11) ax.grid(True, axis='y', alpha=0.3) plt.tight_layout() fig.savefig(os.path.join(FIG_DIR, '2021_U5_5_fig4.png'), bbox_inches='tight') plt.close(fig) print("fig4 saved") |
fig4 saved
fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。plt.subplots(figsize=(W, H)) で図サイズ指定、fig.savefig(..., bbox_inches='tight') で余白を自動で詰めて保存。255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | print("\n========== HTML用 統計サマリー ==========") print(f"分析年度: 2022年度") print(f"分析対象: {len(df_ana)}都道府県") print(f"決定係数 R²: {r2:.3f}") print(f"自由度調整済み R²: {r2_adj:.3f}") print(f"F統計量: {f_stat:.2f} p値: {f_pval:.4f}") print(f"保育所密度 vs 合計特殊出生率: r = {r_birth_hoiku:.3f}, p = {p_birth_hoiku:.4f}") print("\n-- 標準化偏回帰係数 --") for v in x_vars: b = ols_model.params[v] p = ols_model.pvalues[v] ci_lo = ols_model.conf_int().loc[v, 0] ci_hi = ols_model.conf_int().loc[v, 1] sig = '*' if p < 0.05 else '' print(f" {v}: β={b:.3f} CI=[{ci_lo:.3f}, {ci_hi:.3f}] p={p:.4f} {sig}") print("\n-- 相関行列(ソーシャルキャピタル変数)--") for i, v1 in enumerate(sc_vars): for j, v2 in enumerate(sc_vars): if j > i: r, p = stats.pearsonr(df_ana[v1], df_ana[v2]) if abs(r) > 0.4: sig = '**' if p < 0.01 else ('*' if p < 0.05 else '') print(f" {v1} ↔ {v2}: r={r:.3f} p={p:.4f} {sig}") print("\n-- 都道府県別クラスター(閾値 = Z[-4,2])--") from scipy.cluster.hierarchy import fcluster labels_clust = fcluster(Z, t=4, criterion='maxclust') for i, pref in enumerate(pref_names): print(f" {pref}: クラスター{labels_clust[i]}") print("\n全図の保存先:", FIG_DIR) print("スクリプト完了") |
========== HTML用 統計サマリー ========== 分析年度: 2022年度 分析対象: 47都道府県 決定係数 R²: 0.549 自由度調整済み R²: 0.468 F統計量: 6.78 p値: 0.0000 保育所密度 vs 合計特殊出生率: r = 0.628, p = 0.0000 -- 標準化偏回帰係数 -- 保育所密度: β=0.062 CI=[0.021, 0.102] p=0.0041 * 高齢化率: β=-0.052 CI=[-0.164, 0.059] p=0.3497 リサイクル率: β=0.017 CI=[-0.021, 0.056] p=0.3747 進学率: β=-0.046 CI=[-0.100, 0.009] p=0.0989 婚姻率: β=-0.016 CI=[-0.119, 0.088] p=0.7628 教養娯楽費率: β=-0.028 CI=[-0.073, 0.016] p=0.2039 医療施設密度: β=0.053 CI=[0.002, 0.104] p=0.0417 * -- 相関行列(ソーシャルキャピタル変数)-- 保育所密度 ↔ 進学率: r=-0.569 p=0.0000 ** 保育所密度 ↔ 教養娯楽費率: r=-0.519 p=0.0002 ** 高齢化率 ↔ 進学率: r=-0.588 p=0.0000 ** 高齢化率 ↔ 婚姻率: r=-0.890 p=0.0000 ** 高齢化率 ↔ 教養娯楽費率: r=-0.400 p=0.0053 ** 高齢化率 ↔ 教育費率: r=-0.527 p=0.0001 ** 進学率 ↔ 婚姻率: r=0.555 p=0.0001 ** 進学率 ↔ 教養娯楽費率: r=0.627 p=0.0000 ** 進学率 ↔ 教育費率: r=0.464 p=0.0010 ** 婚姻率 ↔ 教育費率: r=0.444 p=0.0017 ** -- 都道府県別クラスター(閾値 = Z[-4,2])-- 北海道: クラスター3 青森県: クラスター1 岩手県: クラスター1 宮城県: クラスター4 秋田県: クラスター1 山形県: クラスター1 福島県: クラスター4 茨城県: クラスター3 栃木県: クラスター4 群馬県: クラスター4 埼玉県: クラスター2 千葉県: クラスター2 東京都: クラスター2 神奈川県: クラスター2 新潟県: クラスター1 富山県: クラスター3 石川県: クラスター4 福井県: クラスター4 山梨県: クラスター4 長野県: クラスター3 岐阜県: クラスター4 静岡県: クラスター4 愛知県: クラスター2 三重県: クラスター3 滋賀県: クラスター4 京都府: クラスター4 大阪府: クラスター4 兵庫県: クラスター4 奈良県: クラスター4 和歌山県: クラスター4 鳥取県: クラスター3 島根県: クラスター1 岡山県: クラスター3 広島県: クラスター3 山口県: クラスター3 徳島県: クラスター4 香川県: クラスター3 愛媛県: クラスター4 高知県: クラスター1 福岡県: クラスター3 佐賀県: クラスター1 長崎県: クラスター1 熊本県: クラスター1 大分県: クラスター1 宮崎県: クラスター1 鹿児島県: クラスター1 沖縄県: クラスター2 全図の保存先: html/figures スクリプト完了
import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。.dropna() は欠損行を除去、.copy() は独立したコピーを作る。pandasで警告を防ぐ定石。本研究は SSDSE-B(2022 年度, 47 都道府県)を用いて、行政統計変数でソーシャルキャピタルを代理し、地域コミュニティ活動と合計特殊出生率の関係を定量的に分析した。
子育て支援施設(保育所)と地域医療の充実が、ソーシャルキャピタルを強化し出生率を高めるという仮説を統計的に支持する結果が得られた。政策的には、クラスターごとに異なるアプローチが有効であり、「地方の保育所整備」と「都市部の待機児童解消」は方向性は同じでも実施手段が異なることが示唆される。
本研究の手法は、2021 年度コンペ当時としては プロキシ変数による社会概念の操作化・重回帰+クラスタリングの組み合わせ という点で革新的であり、審査員奨励賞を受賞した。今後は SSDSE-E(社会生活統計指標)や社会調査データとの組み合わせによる、より直接的なソーシャルキャピタル測定が望まれる。
データ出典: SSDSE-B-2026(社会・人口統計体系データセット B), 政府統計の総合窓口(e-Stat)。
使用年度: 2022 年度断面データ(47 都道府県)。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。