このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
日本の合計特殊出生率(TFR)は1970年代から低下を続け、2022年には過去最低の1.26を記録した。少子化の要因は複合的であるが、本研究は「保育環境の整備」が出生率に与える影響に着目し、都道府県別データを用いた統計的分析を行った。
まず「少子化と保育環境都道府県別出生率と保育所整備の関係分析」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。
SSDSE-B 2026 相関分析 OLS重回帰 時系列分析 代理変数設計
SSDSE-B-2026(社会・人口統計体系データセット,都道府県版)を使用。2012〜2023年度の47都道府県パネルデータから、主に2022年度断面データを分析に用いる。
| データ項目 | 概要 | 利用年度 |
|---|---|---|
| 合計特殊出生率(TFR) | 一人の女性が生涯に産む子どもの推定数 | 2012〜2022 |
| 保育所等数・定員・待機児童数 | 保育環境の整備状況 | 2022 |
| 総人口・年齢別人口 | 人口構造の把握 | 2022 |
| 消費支出(二人以上世帯) | 生活水準・所得水準の代理 | 2022 |
SSDSE-Bには個票データがないため、観察できない概念を測定可能な指標として定式化する「代理変数設計」が必要になる。
実際に測定したい概念(「保育環境の充実度」「子育てしやすさ」)を直接観測できない場合、相関する測定可能な変数(保育所密度・待機児童率)で代替する手法を「代理変数設計」という。社会科学データ分析の核心的スキル。
設計上の注意点:①代理変数が真の概念と十分な相関を持つか、②複数の代理変数を組み合わせて多面的に測定する、③代理変数固有の誤差(測定誤差)が推定にバイアスを与えないかを確認する。
2012〜2022年の都道府県別TFRを地域区分(8地方)で色分けして可視化した。全国的な低下傾向の中で、地域によって異なるパターンが見られる。
| 地方区分 | 2022年TFR(中央値) | 特徴 |
|---|---|---|
| 九州・沖縄 | 高め(1.5〜1.7程度) | 沖縄は全国最高、九州各県も高水準 |
| 四国・中国 | 中程度 | 地方農村部に農村出生率の名残 |
| 東北・北海道 | 中程度 | 高齢化進展で近年低下傾向 |
| 関東・近畿 | 低め(1.0〜1.3程度) | 都市部の保育所不足・住宅費が影響 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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) |
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} のように書式も指定できます。20 21 22 23 24 25 | # ── データ読み込み ────────────────────────────────────────────────────────── df_raw = pd.read_csv(DATA_B, encoding='cp932', header=1) # 都道府県行のみ抽出 (地域コード R#####) df = df_raw[df_raw['地域コード'].str.match(r'^R\d{5}$', na=False)].copy() df['年度'] = df['年度'].astype(int) |
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ループ不要なのが強み。26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | # ── 変数構築 ────────────────────────────────────────────────────────────── df['TFR'] = pd.to_numeric(df['合計特殊出生率'], errors='coerce') df['保育所密度'] = ( pd.to_numeric(df['保育所等数'], errors='coerce') / pd.to_numeric(df['総人口'], errors='coerce') * 10000 ) df['保育所待機児童率'] = ( pd.to_numeric(df['保育所等利用待機児童数'], errors='coerce') / pd.to_numeric(df['保育所等定員数'], errors='coerce') * 100 ) df['高齢化率'] = ( pd.to_numeric(df['65歳以上人口'], errors='coerce') / pd.to_numeric(df['総人口'], errors='coerce') * 100 ) df['女性就業代理'] = ( pd.to_numeric(df['15~64歳人口(女)'], errors='coerce') / pd.to_numeric(df['15~64歳人口'], errors='coerce') * 100 ) df['消費支出_log'] = np.log( pd.to_numeric(df['消費支出(二人以上の世帯)'], errors='coerce') ) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。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 77 78 79 80 81 82 83 84 85 86 87 88 | # 地域区分マッピング(標準的な8地方区分) region_map = { '北海道': '北海道', '青森県': '東北', '岩手県': '東北', '宮城県': '東北', '秋田県': '東北', '山形県': '東北', '福島県': '東北', '茨城県': '関東', '栃木県': '関東', '群馬県': '関東', '埼玉県': '関東', '千葉県': '関東', '東京都': '関東', '神奈川県': '関東', '新潟県': '中部', '富山県': '中部', '石川県': '中部', '福井県': '中部', '山梨県': '中部', '長野県': '中部', '岐阜県': '中部', '静岡県': '中部', '愛知県': '中部', '三重県': '近畿', '滋賀県': '近畿', '京都府': '近畿', '大阪府': '近畿', '兵庫県': '近畿', '奈良県': '近畿', '和歌山県': '近畿', '鳥取県': '中国', '島根県': '中国', '岡山県': '中国', '広島県': '中国', '山口県': '中国', '徳島県': '四国', '香川県': '四国', '愛媛県': '四国', '高知県': '四国', '福岡県': '九州・沖縄', '佐賀県': '九州・沖縄', '長崎県': '九州・沖縄', '熊本県': '九州・沖縄', '大分県': '九州・沖縄', '宮崎県': '九州・沖縄', '鹿児島県': '九州・沖縄', '沖縄県': '九州・沖縄', } df['地方'] = df['都道府県'].map(region_map) region_colors = { '北海道': '#1565C0', '東北': '#00838F', '関東': '#E65100', '中部': '#558B2F', '近畿': '#6A1B9A', '中国': '#AD1457', '四国': '#37474F', '九州・沖縄': '#F9A825', } fig1, ax1 = plt.subplots(figsize=(12, 7)) for region, color in region_colors.items(): prefs_in_region = [p for p, r in region_map.items() if r == region] for pref in prefs_in_region: subset = df[df['都道府県'] == pref].sort_values('年度') if subset.empty or subset['TFR'].isna().all(): continue ax1.plot(subset['年度'], subset['TFR'], color=color, alpha=0.55, linewidth=1.2, zorder=2) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | # 全国平均(各年の中央値) yearly_med = df.groupby('年度')['TFR'].median() ax1.plot(yearly_med.index, yearly_med.values, color='black', linewidth=2.5, linestyle='--', zorder=5, label='全国中央値') # 凡例(地方区分) from matplotlib.lines import Line2D legend_handles = [ Line2D([0], [0], color=c, linewidth=2.5, label=r) for r, c in region_colors.items() ] legend_handles.append( Line2D([0], [0], color='black', linewidth=2.5, linestyle='--', label='全国中央値') ) ax1.legend(handles=legend_handles, loc='lower left', fontsize=9, ncol=2, framealpha=0.85) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。df.groupby('列').apply(関数) — グループごとに関数を適用。時系列や地域別の集計でよく使います。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | # 注目年をハイライト ax1.axvline(2022, color='red', linewidth=1.2, linestyle=':', alpha=0.7, zorder=3) ax1.text(2022.05, ax1.get_ylim()[1] * 0.98, '2022年', color='red', fontsize=9, va='top') ax1.set_xlabel('年度', fontsize=12) ax1.set_ylabel('合計特殊出生率(TFR)', fontsize=12) ax1.set_title('Fig 1: 都道府県別 合計特殊出生率の時系列推移(地域別色分け)', fontsize=13, fontweight='bold', pad=12) ax1.set_xlim(2012, 2023) ax1.set_xticks(range(2012, 2024)) ax1.grid(axis='y', linestyle='--', alpha=0.4) ax1.spines['top'].set_visible(False) ax1.spines['right'].set_visible(False) plt.tight_layout() fig1_path = os.path.join(FIG_DIR, '2022_H5_1_fig1_tfr_timeseries.png') fig1.savefig(fig1_path, dpi=150, bbox_inches='tight') plt.close(fig1) print(f'Saved: {fig1_path}') |
Saved: html/figures/2022_H5_1_fig1_tfr_timeseries.png
ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。2022年の47都道府県データを用い、「保育所密度(人口1万人あたり保育所等数)」とTFRの関係を散布図で可視化した。各都道府県をラベル付きで表示し、地域パターンを読み取る。
ピアソン積率相関係数 r は2変数の線形関係の強さを-1〜+1で表す。r > 0 なら正の相関(一方が増えると他方も増える傾向)、r < 0 なら負の相関。p値は「相関係数がゼロである」という帰無仮説に対する検定結果。
重要な注意:相関関係は因果関係を意味しない。「保育所が多い地域でTFRが高い」という相関は、①保育所整備がTFR向上に寄与する、②高TFRの地域で保育需要が高まり整備が進む、③第三の変数(地方の文化・経済的余裕)が両方を動かす、のいずれかの可能性がある。
126 127 128 129 130 131 132 133 134 | df22 = df[df['年度'] == 2022].copy().dropna(subset=['TFR', '保育所密度']) fig2, ax2 = plt.subplots(figsize=(12, 8)) for region, color in region_colors.items(): mask = df22['地方'] == region ax2.scatter(df22.loc[mask, '保育所密度'], df22.loc[mask, 'TFR'], color=color, s=60, alpha=0.85, zorder=3, label=region, edgecolors='white', linewidths=0.5) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。135 136 137 138 139 140 141 142 | # 回帰直線 x_arr = df22['保育所密度'].values y_arr = df22['TFR'].values slope, intercept, r_val, p_val, _ = stats.linregress(x_arr, y_arr) x_line = np.linspace(x_arr.min(), x_arr.max(), 200) ax2.plot(x_line, intercept + slope * x_line, color='#C62828', linewidth=1.8, linestyle='--', zorder=2, label=f'回帰直線 (r={r_val:.3f}, p={p_val:.3f})') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。stats.linregress(x, y) — 単回帰の傾き・切片・r値・p値・標準誤差を返します。使わない値は _ で受け取り。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | # 都道府県ラベル(全47都道府県) for _, row in df22.iterrows(): label = row['都道府県'].replace('県', '').replace('府', '').replace('都', '').replace('道', '') ax2.annotate(label, xy=(row['保育所密度'], row['TFR']), xytext=(3, 3), textcoords='offset points', fontsize=6.5, color='#333333', zorder=4) ax2.set_xlabel('保育所密度(保育所等数 / 総人口 × 10,000)', fontsize=12) ax2.set_ylabel('合計特殊出生率(TFR)', fontsize=12) ax2.set_title('Fig 2: 保育所密度 vs 合計特殊出生率(2022年、都道府県別)', fontsize=13, fontweight='bold', pad=12) ax2.legend(fontsize=9, loc='upper right', framealpha=0.85) ax2.grid(linestyle='--', alpha=0.35) ax2.spines['top'].set_visible(False) ax2.spines['right'].set_visible(False) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。for _, row in df.iterrows() — DataFrameを1行ずつ取り出すループ。1点ずつ描画したいときに使用。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。159 160 161 162 163 164 165 166 167 168 169 | # 統計情報を右下に表示 info_text = f'N=47都道府県\nr = {r_val:.3f}\np = {p_val:.3f}' ax2.text(0.02, 0.03, info_text, transform=ax2.transAxes, fontsize=10, verticalalignment='bottom', bbox=dict(boxstyle='round', facecolor='#FFF9C4', alpha=0.85)) plt.tight_layout() fig2_path = os.path.join(FIG_DIR, '2022_H5_1_fig2_scatter_nursery_tfr.png') fig2.savefig(fig2_path, dpi=150, bbox_inches='tight') plt.close(fig2) print(f'Saved: {fig2_path}') |
Saved: html/figures/2022_H5_1_fig2_scatter_nursery_tfr.png
r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。単変量の相関分析では「交絡変数(confounder)」の影響を制御できない。そこで、複数の説明変数を同時にモデルに投入するOLS(最小二乗法)重回帰を実施した。全変数を標準化してから回帰することで、変数間の係数の大きさを比較可能にした。
| 変数 | 標準化係数 | p値 | 有意性 | 解釈 |
|---|---|---|---|---|
| 保育所密度 | +0.092 | 0.000 | *** 有意 | 保育所整備がTFR向上に貢献 |
| 保育所待機児童率 | +0.016 | 0.469 | n.s. | 密度で制御後は有意でない |
| 高齢化率 | +0.008 | 0.723 | n.s. | 単年断面では効果不明確 |
| 女性就業代理 | +0.023 | 0.269 | n.s. | 測定の粗さが原因の可能性 |
| 消費支出(log) | +0.007 | 0.748 | n.s. | 所得効果は都道府県間では希薄 |
| モデル全体: R² = 0.430、Adj.R² = 0.360、F統計量 = 6.18(p < 0.001) | ||||
OLS(最小二乗法)は残差平方和を最小化することで回帰係数を推定する。複数の変数を投入することで「他の変数を一定に保ったときの効果(偏効果)」を測定できる。
係数を比較するには「標準化」が必要。単位の異なる変数(人数・率・金額)をそのまま比較すると係数の大きさが変数のスケールに依存してしまうため、各変数を平均0・標準偏差1に変換してから回帰する。
171 172 173 174 175 176 177 178 179 180 181 182 183 | df22_reg = df22.dropna(subset=['TFR', '保育所密度', '保育所待機児童率', '高齢化率', '女性就業代理', '消費支出_log']) VARS = { '保育所密度\n(人口1万対)': '保育所密度', '保育所\n待機児童率(%)': '保育所待機児童率', '高齢化率(%)': '高齢化率', '女性就業\n代理指標(%)': '女性就業代理', '消費支出\n(log)': '消費支出_log', } X_cols = list(VARS.values()) X_data = df22_reg[X_cols].copy() |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | # 標準化(係数の比較のため) X_std = (X_data - X_data.mean()) / X_data.std() X_sm = sm.add_constant(X_std) y_sm = df22_reg['TFR'].values ols_model = sm.OLS(y_sm, X_sm).fit() coef_df = pd.DataFrame({ '変数': list(VARS.keys()), '係数': ols_model.params[1:], 'se': ols_model.bse[1:], 'p値': ols_model.pvalues[1:], }) coef_df = coef_df.sort_values('係数') colors_bar = ['#C62828' if c < 0 else '#1565C0' for c in coef_df['係数']] sig_alpha = [1.0 if p < 0.05 else 0.45 for p in coef_df['p値']] fig3, ax3 = plt.subplots(figsize=(9, 6)) bars = ax3.barh(coef_df['変数'], coef_df['係数'], color=colors_bar, alpha=0.85, edgecolor='white', linewidth=0.8, height=0.55, zorder=3) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。sm.add_constant(X) — 切片項(定数1の列)を先頭に追加。statsmodelsで必須。sm.OLS(y, X).fit() — 最小二乗法でモデルを推定。model.params, model.pvalues, model.conf_int() で結果取得。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | # 透明度によるp値表示(アルファを個別設定は困難なのでエラーバーで表現) ax3.errorbar(coef_df['係数'], coef_df['変数'], xerr=1.96 * coef_df['se'], fmt='none', color='#333333', capsize=5, linewidth=1.5, zorder=4) # 有意ラベル for i, (_, row) in enumerate(coef_df.iterrows()): sig = '***' if row['p値'] < 0.001 else ('**' if row['p値'] < 0.01 else ('*' if row['p値'] < 0.05 else 'n.s.')) x_pos = row['係数'] + 1.96 * row['se'] + 0.003 ax3.text(x_pos, row['変数'], sig, va='center', fontsize=10, color='#C62828' if 'n.s.' not in sig else '#888888') ax3.axvline(0, color='black', linewidth=1.0, zorder=2) ax3.set_xlabel('標準化回帰係数(95%CI)', fontsize=12) ax3.set_title(f'Fig 3: TFRの決定要因 — OLS回帰係数プロット(2022年、N={len(df22_reg)})', fontsize=13, fontweight='bold', pad=12) r2_text = f'R² = {ols_model.rsquared:.3f}\nAdj.R² = {ols_model.rsquared_adj:.3f}\nN = {len(df22_reg)}' ax3.text(0.97, 0.04, r2_text, transform=ax3.transAxes, fontsize=9.5, ha='right', va='bottom', bbox=dict(boxstyle='round', facecolor='#E3F2FD', alpha=0.9)) ax3.grid(axis='x', linestyle='--', alpha=0.4, zorder=1) ax3.spines['top'].set_visible(False) ax3.spines['right'].set_visible(False) from matplotlib.patches import Patch legend_elements = [ Patch(facecolor='#1565C0', label='正の効果(TFR増加)'), Patch(facecolor='#C62828', label='負の効果(TFR減少)'), ] ax3.legend(handles=legend_elements, loc='lower right', fontsize=9) plt.tight_layout() fig3_path = os.path.join(FIG_DIR, '2022_H5_1_fig3_ols_coef.png') fig3.savefig(fig3_path, dpi=150, bbox_inches='tight') plt.close(fig3) print(f'Saved: {fig3_path}') print(ols_model.summary()) |
Saved: html/figures/2022_H5_1_fig3_ols_coef.png
OLS Regression Results
==============================================================================
Dep. Variable: y R-squared: 0.430
Model: OLS Adj. R-squared: 0.360
Method: Least Squares F-statistic: 6.185
Date: Mon, 18 May 2026 Prob (F-statistic): 0.000234
Time: 11:24:08 Log-Likelihood: 36.387
No. Observations: 47 AIC: -60.77
Df Residuals: 41 BIC: -49.67
Df Model: 5
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const 1.3583 0.017 77.956 0.000 1.323 1.393
保育所密度 0.0917 0.021 4.426 0.000 0.050 0.134
保育所待機児童率 0.0160 0.022 0.731 0.469 -0.028 0.060
高齢化率 0.0084 0.023 0.357 0.723 -0.039 0.056
女性就業代理 0.0228 0.020 1.120 0.269 -0.018 0.064
消費支出_log 0.0073 0.022 0.324 0.748 -0.038 0.052
==============================================================================
Omnibus: 5.870 Durbin-Watson: 0.775
Prob(Omnibus): 0.053 Jarque-Bera (JB): 5.712
Skew: -0.849 Prob(JB): 0.0575
Kurtosis: 2.817 Cond. No. 2.41
==============================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。for _, row in df.iterrows() — DataFrameを1行ずつ取り出すループ。1点ずつ描画したいときに使用。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。保育所への需要が定員を超過した結果が「待機児童」である。2022年時点での都道府県別待機児童率(待機児童数 / 定員数 × 100)をランキング形式で可視化した。TFRの中央値を基準に色分けすることで、待機児童率とTFRの関係を直感的に示す。
横棒グラフによるランキング可視化は「比較」に優れているが、因果関係の解釈には注意が必要。待機児童率が高い地域でTFRが高い場合、①高TFR → 高保育需要 → 高待機児童率、②共通の第三変数(伝統的家族観など)が両方を規定、の可能性がある。
色分けによる第三変数(TFR水準)の視覚的表現は、二変数の散布図では見えにくいパターンを浮かび上がらせる効果的な手法。
248 249 250 251 252 253 254 255 256 257 258 259 260 | df22_wait = df22.dropna(subset=['保育所待機児童率']).copy() df22_wait = df22_wait.sort_values('保育所待機児童率', ascending=True) # TFRに基づいて棒の色を決定 tfr_mid = df22_wait['TFR'].median() bar_colors = ['#E65100' if t >= tfr_mid else '#546E7A' for t in df22_wait['TFR'].values] fig4, ax4 = plt.subplots(figsize=(10, 13)) bars4 = ax4.barh(df22_wait['都道府県'], df22_wait['保育所待機児童率'], color=bar_colors, alpha=0.85, edgecolor='white', linewidth=0.5, height=0.72, zorder=3) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。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 289 290 291 | # 値ラベル for bar, val in zip(bars4, df22_wait['保育所待機児童率']): if val > 0: ax4.text(val + 0.005, bar.get_y() + bar.get_height() / 2, f'{val:.3f}%', va='center', fontsize=7.5, color='#212121') ax4.set_xlabel('保育所待機児童率(待機児童数 / 定員数 × 100, %)', fontsize=11) ax4.set_title('Fig 4: 保育所待機児童率 都道府県別ランキング(2022年)', fontsize=13, fontweight='bold', pad=12) ax4.grid(axis='x', linestyle='--', alpha=0.4, zorder=1) ax4.spines['top'].set_visible(False) ax4.spines['right'].set_visible(False) from matplotlib.patches import Patch legend_elems4 = [ Patch(facecolor='#E65100', label=f'TFR ≥ 中央値({tfr_mid:.2f})'), Patch(facecolor='#546E7A', label=f'TFR < 中央値({tfr_mid:.2f})'), ] ax4.legend(handles=legend_elems4, loc='lower right', fontsize=9, framealpha=0.85) plt.tight_layout() fig4_path = os.path.join(FIG_DIR, '2022_H5_1_fig4_waitlist_ranking.png') fig4.savefig(fig4_path, dpi=150, bbox_inches='tight') plt.close(fig4) print(f'Saved: {fig4_path}') print('\n=== 完了 ===') print(f'Fig1: {fig1_path}') print(f'Fig2: {fig2_path}') print(f'Fig3: {fig3_path}') print(f'Fig4: {fig4_path}') |
Saved: html/figures/2022_H5_1_fig4_waitlist_ranking.png === 完了 === Fig1: html/figures/2022_H5_1_fig1_tfr_timeseries.png Fig2: html/figures/2022_H5_1_fig2_scatter_nursery_tfr.png Fig3: html/figures/2022_H5_1_fig3_ols_coef.png Fig4: html/figures/2022_H5_1_fig4_waitlist_ranking.png
import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。SSDSE-B-2026の47都道府県データを用いた分析から、以下の知見が得られた:
| データ | 出典・説明 |
|---|---|
| SSDSE-B-2026.csv | 社会・人口統計体系データセット(都道府県版)。統計数理研究所提供。2012〜2023年度、47都道府県、112変数。 |
| 合計特殊出生率 | SSDSE-B収録。原典は厚生労働省「人口動態統計」 |
| 保育所等数・定員・待機児童数 | SSDSE-B収録。原典は厚生労働省「保育所等関連状況取りまとめ」 |
| 人口データ(総人口・年齢別) | SSDSE-B収録。原典は総務省統計局「住民基本台帳人口移動報告」 |
| 消費支出(二人以上世帯) | SSDSE-B収録。原典は総務省統計局「家計調査」 |
本教育用コードはSSDSE-B-2026.csvの実データのみを使用(合成データなし)。実行環境:Python 3.x、pandas、numpy、matplotlib、statsmodels、scipy。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。