このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
ボランティア活動は「誰が、なぜ行うのか」——この問いは社会科学の重要テーマの一つである。本研究は、都道府県別の統計データを用いて、地域特性・社会資本とボランティア活動(の代理指標)の関係を定量的に分析する。
まず「ボランティア活動の決定要因地域特性・社会資本の相関分析」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。
SSDSE-B Pearson相関 OLS回帰 代理変数 社会資本理論
ロバート・パットナム(Robert Putnam, 1993, 2000)は、社会資本(Social Capital)を「信頼・規範・ネットワーク」という3つの要素で構成されると定義した。社会資本が豊かな地域では、住民間の協力が促進され、ボランティア活動も活発になると予測される。
| 社会資本の構成要素 | Putnamの定義 | 本研究での着目点 |
|---|---|---|
| 信頼(Trust) | 他者への一般的信頼感 | 婚姻率(対人関係の安定性) |
| 規範(Norms) | 互酬性の規範(助け合い) | 保育所密度(地域相互扶助) |
| ネットワーク(Networks) | 市民的参加のネットワーク | 地域コミュニティ施設密度 |
測定したい概念を直接観察できない場合、理論的に関連する別の変数で代替する。これを代理変数という。代理変数の妥当性(validity)の確認が不可欠だ。
代理変数を使う際の3つのステップ:
社会資本関連指標 7変数のPearson相関係数行列をヒートマップで可視化する。赤が正の相関、青が負の相関、白がゼロに近い相関を示す。
| 変数ペア | 相関の方向 | 解釈 |
|---|---|---|
| 婚姻率 ↔ 高齢化率 | 強い負 | 高齢化が進む地域ほど婚姻率が低い(人口構造の反映) |
| 婚姻率 ↔ 離婚率 | 正 | 婚姻件数が多い地域は離婚も多い(結婚活動全般の活発さ) |
| 高齢化率 ↔ 大学進学率 | 負 | 高齢化が進む地域ほど若者の大学進学率が低い傾向 |
| 消費支出_log ↔ 大学進学率 | 正 | 消費水準が高い地域(都市部)は教育への投資も多い |
| 教育費 ↔ 大学進学率 | 正 | 教育費支出と進学率は正に連動 |
相関係数は2変数の線形関係の強さを −1 〜 +1 で表す。しかし相関は因果関係を意味しない。例えば「アイスクリームの売上と溺死者数の相関」は、両方が夏の気温という交絡変数(confound)で説明できる。
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_2022 = df_b[df_b['年度'] == 2022].copy() |
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} のように書式も指定できます。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 70 71 72 73 74 75 76 | # 変数生成 df_2022['婚姻率'] = df_2022['婚姻件数'] / df_2022['総人口'] * 1000 df_2022['保育所密度'] = df_2022['保育所等数'] / df_2022['総人口'] * 10000 df_2022['高齢化率'] = df_2022['65歳以上人口'] / df_2022['総人口'] * 100 df_2022['大学進学率'] = df_2022['高等学校卒業者のうち進学者数'] / df_2022['高等学校卒業者数'].replace(0, np.nan) * 100 df_2022['消費支出_log'] = np.log(df_2022['消費支出(二人以上の世帯)'].clip(lower=1)) df_2022['教育費_万円'] = df_2022['教育費(二人以上の世帯)'] / 10000 df_2022['離婚率'] = df_2022['離婚件数'] / df_2022['総人口'] * 1000 region_map = { '北海道': '北海道・東北', '青森県': '北海道・東北', '岩手県': '北海道・東北', '宮城県': '北海道・東北', '秋田県': '北海道・東北', '山形県': '北海道・東北', '福島県': '北海道・東北', '茨城県': '関東', '栃木県': '関東', '群馬県': '関東', '埼玉県': '関東', '千葉県': '関東', '東京都': '関東', '神奈川県': '関東', '新潟県': '中部', '富山県': '中部', '石川県': '中部', '福井県': '中部', '山梨県': '中部', '長野県': '中部', '岐阜県': '中部', '静岡県': '中部', '愛知県': '中部', '三重県': '近畿', '滋賀県': '近畿', '京都府': '近畿', '大阪府': '近畿', '兵庫県': '近畿', '奈良県': '近畿', '和歌山県': '近畿', '鳥取県': '中国・四国', '島根県': '中国・四国', '岡山県': '中国・四国', '広島県': '中国・四国', '山口県': '中国・四国', '徳島県': '中国・四国', '香川県': '中国・四国', '愛媛県': '中国・四国', '高知県': '中国・四国', '福岡県': '九州・沖縄', '佐賀県': '九州・沖縄', '長崎県': '九州・沖縄', '熊本県': '九州・沖縄', '大分県': '九州・沖縄', '宮崎県': '九州・沖縄', '鹿児島県': '九州・沖縄', '沖縄県': '九州・沖縄', } df_2022['地域'] = df_2022['都道府県'].map(region_map) region_colors = { '北海道・東北': '#4e9af1', '関東': '#e05c5c', '中部': '#f0a500', '近畿': '#5cb85c', '中国・四国': '#9b59b6', '九州・沖縄': '#f39c12', } region_order = ['北海道・東北', '関東', '中部', '近畿', '中国・四国', '九州・沖縄'] analysis_vars = ['婚姻率', '保育所密度', '高齢化率', '大学進学率', '消費支出_log', '教育費_万円', '離婚率'] df_corr = df_2022[analysis_vars].dropna() corr = df_corr.corr() fig, ax = plt.subplots(figsize=(9, 7)) im = ax.imshow(corr, cmap='RdBu_r', vmin=-1, vmax=1) ax.set_xticks(range(len(analysis_vars))) ax.set_yticks(range(len(analysis_vars))) ax.set_xticklabels(analysis_vars, rotation=45, ha='right', fontsize=9) ax.set_yticklabels(analysis_vars, fontsize=9) for i in range(len(analysis_vars)): for j in range(len(analysis_vars)): val = corr.iloc[i, j] ax.text(j, i, f'{val:.2f}', ha='center', va='center', fontsize=7.5, color='white' if abs(val) > 0.5 else 'black') plt.colorbar(im, ax=ax, label='Pearson相関係数') ax.set_title('社会資本指標間の相関ヒートマップ(2022年, N=47)', fontsize=13, fontweight='bold') plt.tight_layout() plt.savefig(os.path.join(FIG_DIR, '2022_H2_fig1_corr.png'), dpi=150, bbox_inches='tight') plt.close() print("Fig1 saved") |
Fig1 saved
fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。高齢化率(X軸)と保育所密度(Y軸)の散布図を地域ブロック別に色分けして描く。回帰直線とPearson相関係数・p値を重ねて表示する。
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | df_sc = df_2022[['都道府県', '高齢化率', '保育所密度', '地域']].dropna() fig, ax = plt.subplots(figsize=(9, 6)) for reg, grp in df_sc.groupby('地域'): ax.scatter(grp['高齢化率'], 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['高齢化率'], row['保育所密度']), fontsize=7, alpha=0.7, xytext=(3, 3), textcoords='offset points') slope, intercept, r, p, _ = stats.linregress(df_sc['高齢化率'], df_sc['保育所密度']) xr = np.linspace(df_sc['高齢化率'].min(), df_sc['高齢化率'].max(), 100) ax.plot(xr, slope * xr + intercept, 'k--', linewidth=1.5, label=f'回帰直線 (r={r:.2f}, p={p:.3f})') ax.set_xlabel('高齢化率(%)', fontsize=12) ax.set_ylabel('保育所密度(/人口万対)', fontsize=12) ax.set_title('高齢化率 vs 保育所密度(2022年, N=47)\n(地域コミュニティ構造の可視化)', fontsize=12, fontweight='bold') ax.legend(fontsize=8, ncol=2) ax.grid(alpha=0.3) plt.tight_layout() plt.savefig(os.path.join(FIG_DIR, '2022_H2_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ループ不要なのが強み。社会的絆の代理指標として婚姻率を目的変数に設定し、地域特性4変数を説明変数とするOLS重回帰を実施する。
| 説明変数 | 係数(β) | p値 | 有意性 | 解釈 |
|---|---|---|---|---|
| 高齢化率 | −0.124 | <0.001 | *** | 高齢化が1%pt上昇すると婚姻率が0.124件/千人低下 |
| 大学進学率 | +0.007 | 0.281 | n.s. | 有意な関連なし(高齢化率で説明済みの可能性) |
| 消費支出(log) | −0.485 | 0.392 | n.s. | 有意な関連なし |
| 保育所密度 | +0.038 | 0.505 | n.s. | 有意な関連なし(方向は仮説通り正) |
| モデル全体:R² = 0.803 | F検定 p < 0.001(モデル全体は有意)。分散の80%を説明。 | |||
Pythonでは statsmodels.api.OLS を使って回帰分析を行う。結果の読み方を理解することが重要。
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | 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'婚姻率の決定要因(社会的絆の代理, 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_H2_fig3_ols.png'), dpi=150, bbox_inches='tight') plt.close() print("Fig3 saved") |
OLS Regression Results
==============================================================================
Dep. Variable: 婚姻率 R-squared: 0.803
Model: OLS Adj. R-squared: 0.784
Method: Least Squares F-statistic: 42.70
Date: Mon, 18 May 2026 Prob (F-statistic): 2.84e-14
Time: 11:24:01 Log-Likelihood: 7.9861
No. Observations: 47 AIC: -5.972
Df Residuals: 42 BIC: 3.279
Df Model: 4
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const 13.1445 7.130 1.843 0.072 -1.245 27.534
高齢化率 -0.1238 0.012 -10.198 0.000 -0.148 -0.099
大学進学率 0.0071 0.007 1.091 0.281 -0.006 0.020
消費支出_log -0.4846 0.561 -0.864 0.392 -1.616 0.647
保育所密度 0.0381 0.057 0.673 0.505 -0.076 0.152
==============================================================================
Omnibus: 2.613 Durbin-Watson: 1.648
Prob(Omnibus): 0.271 Jarque-Bera (JB): 2.207
Skew: 0.529 Prob(JB): 0.332
Kurtosis: 2.912 Cond. No. 1.50e+04
==============================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 1.5e+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()。47都道府県を6地域ブロックに分類し、保育所密度と婚姻率の分布を箱ひげ図で比較する。地域間の格差と特性の違いを視覚的に把握する。
| 地域 | 保育所密度の特徴 | 婚姻率の特徴 | 解釈 |
|---|---|---|---|
| 北海道・東北 | 中程度〜やや低い | 低い | 高齢化・人口減少が婚姻率に影響 |
| 関東 | 中程度 | 高め | 都市集積による若年人口維持 |
| 中部 | 中程度 | 中程度 | 工業地帯の雇用安定が基盤 |
| 近畿 | 中程度 | 中程度 | 都市部と農村部の混在 |
| 中国・四国 | 低め〜中程度 | 低め | 地方都市の高齢化進行 |
| 九州・沖縄 | 高い傾向 | 高い | 若い人口構造・活発な社会的ネットワーク |
統計分析の結果をどう政策に活かすか?高校生の視点から考えてみよう。
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 | df_box = df_2022[['地域', '保育所密度', '婚姻率']].dropna() fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5)) bxdata1 = [df_box[df_box['地域'] == reg]['保育所密度'].values for reg in region_order] bp1 = ax1.boxplot(bxdata1, patch_artist=True, labels=[r[:4] for r in region_order]) for patch, reg in zip(bp1['boxes'], region_order): patch.set_facecolor(region_colors.get(reg, 'gray')) patch.set_alpha(0.7) ax1.set_xlabel('地域', fontsize=11) ax1.set_ylabel('保育所密度(/万人)', fontsize=11) ax1.set_title('地域別 保育所密度の分布', fontsize=12, fontweight='bold') ax1.grid(axis='y', alpha=0.3) bxdata2 = [df_box[df_box['地域'] == reg]['婚姻率'].values for reg in region_order] bp2 = ax2.boxplot(bxdata2, patch_artist=True, labels=[r[:4] for r in region_order]) for patch, reg in zip(bp2['boxes'], region_order): patch.set_facecolor(region_colors.get(reg, 'gray')) patch.set_alpha(0.7) ax2.set_xlabel('地域', fontsize=11) ax2.set_ylabel('婚姻率(件/千人)', fontsize=11) ax2.set_title('地域別 婚姻率の分布', fontsize=12, fontweight='bold') ax2.grid(axis='y', alpha=0.3) plt.suptitle('地域ブロック別 社会資本指標の分布(2022年)', fontsize=13, fontweight='bold', y=1.02) plt.tight_layout() plt.savefig(os.path.join(FIG_DIR, '2022_H2_fig4_boxplot.png'), dpi=150, bbox_inches='tight') plt.close() print("Fig4 saved") print("All done!") |
Fig4 saved All done!
fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。SSDSE-B(都道府県別データ, 2022年, N=47)を用いた社会資本の定量分析から、以下の知見が得られた:
| 手法 | 目的 | 使用変数 | 主な結果 |
|---|---|---|---|
| Pearson相関(ヒートマップ) | 指標間の関係構造の把握 | 7指標全体 | 婚姻率・高齢化率の強い負の相関を確認 |
| 散布図+回帰直線 | 2変数関係と地域差の可視化 | 高齢化率、保育所密度 | 地域ブロック間の構造的差異を視覚化 |
| OLS重回帰 | 婚姻率の多変量決定要因の推定 | 4説明変数 | R²=0.803、高齢化率のみ有意(p<0.001) |
| 地域別箱ひげ図 | 6地域ブロック間の格差把握 | 保育所密度、婚姻率 | 九州・沖縄と東北の対比が明確 |
| データ | 出典 | 備考 |
|---|---|---|
| SSDSE-B-2026(都道府県別) | 統計数理研究所 SSDSE(社会・人口統計体系) | 2022年度データを使用 |
| 婚姻件数・離婚件数 | 厚生労働省 人口動態統計(SSDSE-B収録) | 婚姻率・離婚率に変換 |
| 保育所等数・定員数 | 厚生労働省 保育所等関連状況(SSDSE-B収録) | 保育所密度に変換(/万人) |
| 消費支出・教育費(二人以上世帯) | 総務省 家計調査(SSDSE-B収録) | 消費支出は対数変換 |
| 高校卒業者・進学者数 | 文部科学省 学校基本調査(SSDSE-B収録) | 大学進学率の算出に使用 |
本スクリプトはSSDSE-B-2026.csvの実データのみを使用(合成データ・乱数不使用)。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。