このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
熱中症は夏季の高温・多湿環境で体温調節機能が破綻することで発症する。 近年の気候変動による気温上昇を背景に、日本では熱中症による救急搬送件数・死亡者数が増加傾向にある。 特に、体温調節機能が低下しやすい高齢者は高リスク群であり、高齢化が進む地域では医療への負担増が懸念される。
まず「熱中症を防ごう!」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。
気温データ(B4102) 高齢化率(A1303/A1101) 保健医療費割合(L322106/L3221) 相関分析 重回帰分析
SSDSE(社会・人口統計体系)-B は47都道府県の統計データを年度別に収録するパネルデータである。本分析では2022年度の断面データ(N=47)を主に使用し、気温トレンド分析には2012〜2023年の12年分のデータを活用した。
| 変数コード | 変数名 | 単位 | 分析での役割 |
|---|---|---|---|
| B4102 | 最高気温(日最高気温の月平均の最高値) | ℃ | 熱中症リスク主指標 |
| B4101 | 年平均気温 | ℃ | 気温トレンド・相関分析 |
| B4103 | 最低気温 | ℃ | 相関ヒートマップ |
| B4106 | 降水日数(年間) | 日 | 気候条件の制御変数 |
| B4109 | 年降水量 | mm | 気候条件の制御変数 |
| A1303/A1101 ×100 | 高齢化率(65歳以上人口比率) | % | 熱中症高リスク群指標 |
| L322106/L3221 ×100 | 保健医療費割合(消費支出に占める比率) | % | 健康負担の代理指標 |
| I510120/A1101 ×10000 | 病院密度(人口1万人あたり一般病院数) | 院/万人 | 医療インフラ指標 |
| 変数 | 平均 | 標準偏差 | 最小 | 最大 |
|---|---|---|---|---|
| 最高気温(℃) | 32.3 | 3.5 | 22.8 | 37.0 |
| 年平均気温(℃) | 16.1 | 3.5 | 8.8 | 23.1 |
| 高齢化率(%) | 29.9 | 3.8 | 20.5 | 36.9 |
| 保健医療費割合(%) | 5.17 | 0.55 | 4.09 | 6.57 |
| 病院密度(院/万人) | 5.7 | 2.1 | 2.0 | 11.7 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | df_raw = pd.read_csv(DATA_B, encoding='cp932', header=0) # 最初の行(日本語ラベル)を除外し、都道府県行のみ抽出(R+5桁数字) df_all = df_raw.iloc[1:].copy() df_all = df_all[df_all['Code'].str.match(r'^R\d{5}$', na=False)].copy() # 必要列を数値変換 num_cols = ['SSDSE-B-2026', 'A1101', # 総人口 'A1303', # 65歳以上人口 'B4101', # 年平均気温 'B4102', # 最高気温 'B4103', # 最低気温 'B4106', # 降水日数 'B4109', # 年降水量 'L3221', # 消費支出(二人以上の世帯) 'L322106',# 保健医療費(二人以上の世帯) 'I510120', # 一般病院数 ] for c in num_cols: if c in df_all.columns: df_all[c] = pd.to_numeric(df_all[c], errors='coerce') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。pd.read_csv(...) でCSVを読み込みます。encoding='cp932' は日本語Windows由来の文字コード、header=1 は「2行目を列名として使う」。df['地域コード'].str.match(r'^R\d{5}', ...) — 正規表現で「R+数字5桁」の行(47都道府県)だけTrueにし、真偽値で行をフィルタ。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | years_all = sorted(df_all['SSDSE-B-2026'].dropna().unique().astype(int)) ts_temp_avg = [] ts_temp_max = [] for yr in years_all: df_yr = df_all[df_all['SSDSE-B-2026'] == yr] ta = pd.to_numeric(df_yr['B4101'], errors='coerce').mean() tm = pd.to_numeric(df_yr['B4102'], errors='coerce').mean() ts_temp_avg.append(ta) ts_temp_max.append(tm) ts_temp_avg = np.array(ts_temp_avg) ts_temp_max = np.array(ts_temp_max) print("\n" + "=" * 60) print("■ 気温トレンド(全国47都道府県平均)") print("=" * 60) for yr, ta, tm in zip(years_all, ts_temp_avg, ts_temp_max): print(f" {yr}年: 年平均気温={ta:.2f}℃, 最高気温={tm:.2f}℃") |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。.astype(int) — 列を整数に変換(年度などを数値比較するため)。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。43 44 45 46 47 | # トレンド検定(Mann-Kendall 代わりにスピアマン相関) rho_ta, p_ta = stats.spearmanr(years_all, ts_temp_avg) rho_tm, p_tm = stats.spearmanr(years_all, ts_temp_max) print(f"\n 年平均気温トレンド: ρ={rho_ta:.4f}, p={p_ta:.4f}") print(f" 最高気温トレンド : ρ={rho_tm:.4f}, p={p_tm:.4f}") |
============================================================ ■ 気温トレンド(全国47都道府県平均) ============================================================ 2012年: 年平均気温=15.20℃, 最高気温=32.90℃ 2013年: 年平均気温=15.61℃, 最高気温=32.90℃ 2014年: 年平均気温=15.31℃, 最高気温=30.74℃ 2015年: 年平均気温=15.86℃, 最高気温=31.14℃ 2016年: 年平均気温=16.19℃, 最高気温=32.69℃ 2017年: 年平均気温=15.40℃, 最高気温=32.08℃ 2018年: 年平均気温=16.03℃, 最高気温=33.04℃ 2019年: 年平均気温=16.17℃, 最高気温=32.11℃ 2020年: 年平均気温=16.20℃, 最高気温=33.79℃ 2021年: 年平均気温=16.16℃, 最高気温=31.41℃ 2022年: 年平均気温=16.07℃, 最高気温=32.30℃ 2023年: 年平均気温=16.80℃, 最高気温=34.00℃ 年平均気温トレンド: ρ=0.7692, p=0.0034 最高気温トレンド : ρ=0.2587, p=0.4168
r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。47都道府県の最高気温(B4102)と保健医療費割合(L322106/L3221 × 100)の散布図。 気温が高い都道府県(南西部)では保健医療費の割合が高い傾向が見られる。
ピアソン相関係数 r は2変数の線形関係の強さを −1〜+1 で表す。N=47 では |r| ≥ 0.29 程度で p < 0.05 になる(帰無仮説:ρ=0)。ただし、相関は因果を意味しない点に注意が必要。
49 50 51 52 53 54 55 56 57 58 | fig1, ax1 = plt.subplots(figsize=(9, 6)) ax1.scatter(_tm, _hr, color='#E65100', s=55, alpha=0.75, edgecolors='white', linewidths=0.7, zorder=3, label='都道府県') # 回帰直線 z1 = np.polyfit(_tm, _hr, 1) xs1 = np.linspace(_tm.min(), _tm.max(), 200) ax1.plot(xs1, np.poly1d(z1)(xs1), color='#C62828', linewidth=2.0, linestyle='--', alpha=0.85, label='回帰直線') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | # 相関係数 r1, p1 = stats.pearsonr(_tm, _hr) sig1 = '***' if p1 < 0.001 else '**' if p1 < 0.01 else '*' if p1 < 0.05 else 'n.s.' # 注目都道府県をラベル表示(上位・下位) combined1 = list(zip(_tm, _hr, _pn)) top3_heat = sorted(combined1, key=lambda x: x[0], reverse=True)[:3] top3_health = sorted(combined1, key=lambda x: x[1], reverse=True)[:3] label_set1 = {p for _, _, p in top3_heat + top3_health} for tx, ty, pn in combined1: if pn in label_set1: ax1.annotate(pn, (tx, ty), fontsize=8.5, xytext=(5, 4), textcoords='offset points', color='#333') ax1.set_xlabel('最高気温(日最高気温の月平均の最高値、℃)', fontsize=12) ax1.set_ylabel('保健医療費割合(%)', fontsize=12) ax1.set_title(f'最高気温と保健医療費割合の関係\n' f'r = {r1:.3f} ({sig1}), N = {N}都道府県(2022年度)', fontsize=13, fontweight='bold') ax1.legend(fontsize=10) ax1.grid(True, alpha=0.3) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。80 81 82 83 84 85 86 87 88 89 90 | # 解釈メモ ax1.text(0.02, 0.98, '気温が高い地域では\n健康関連支出も高い傾向', transform=ax1.transAxes, fontsize=9, verticalalignment='top', color='#555', bbox=dict(boxstyle='round,pad=0.4', facecolor='#FFF3E0', alpha=0.85)) plt.tight_layout() fig1.savefig(FIG_DIR + '2023_H5_3_fig1_temp_health.png', bbox_inches='tight', dpi=150) plt.close(fig1) print("\n図1保存: 2023_H5_3_fig1_temp_health.png") |
図1保存: 2023_H5_3_fig1_temp_health.png
df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。高齢化率(65歳以上人口比率)と保健医療費割合の散布図。 高齢者は熱中症の高リスク群であると同時に、医療利用率が高い。 高齢化が進む都道府県では医療費割合への影響が懸念される。
AとBに相関が見られても、第三の変数Cが両方に影響している「交絡」の場合がある。例えば「気温が高い地域は若者人口が多い(低高齢化率)→消費支出の内訳が変わる」という経路が考えられる。重回帰分析で複数変数を同時に制御することが重要。
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | fig2, ax2 = plt.subplots(figsize=(9, 6)) ax2.scatter(_ar, _hr, color='#1565C0', s=55, alpha=0.75, edgecolors='white', linewidths=0.7, zorder=3, label='都道府県') z2 = np.polyfit(_ar, _hr, 1) xs2 = np.linspace(_ar.min(), _ar.max(), 200) ax2.plot(xs2, np.poly1d(z2)(xs2), color='#0D47A1', linewidth=2.0, linestyle='--', alpha=0.85, label='回帰直線') r2, p2 = stats.pearsonr(_ar, _hr) sig2 = '***' if p2 < 0.001 else '**' if p2 < 0.01 else '*' if p2 < 0.05 else 'n.s.' combined2 = list(zip(_ar, _hr, _pn)) top3_aging = sorted(combined2, key=lambda x: x[0], reverse=True)[:3] top3_health2 = sorted(combined2, key=lambda x: x[1], reverse=True)[:3] label_set2 = {p for _, _, p in top3_aging + top3_health2} for ax, ay, pn in combined2: if pn in label_set2: ax2.annotate(pn, (ax, ay), fontsize=8.5, xytext=(5, 4), textcoords='offset points', color='#333') ax2.set_xlabel('高齢化率(65歳以上人口比率、%)', fontsize=12) ax2.set_ylabel('保健医療費割合(%)', fontsize=12) ax2.set_title(f'高齢化率と保健医療費割合の関係\n' f'r = {r2:.3f} ({sig2}), N = {N}都道府県(2022年度)', fontsize=13, fontweight='bold') ax2.legend(fontsize=10) ax2.grid(True, alpha=0.3) ax2.text(0.02, 0.98, '高齢化率が高い地域ほど\n保健医療費割合が増大', transform=ax2.transAxes, fontsize=9, verticalalignment='top', color='#555', bbox=dict(boxstyle='round,pad=0.4', facecolor='#E3F2FD', alpha=0.85)) plt.tight_layout() fig2.savefig(FIG_DIR + '2023_H5_3_fig2_aging_health.png', bbox_inches='tight', dpi=150) plt.close(fig2) print("図2保存: 2023_H5_3_fig2_aging_health.png") |
図2保存: 2023_H5_3_fig2_aging_health.png
fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。SSDSE-B の47都道府県平均値を用いた2012〜2023年の気温推移。 年平均気温(青)と最高気温(橙)の長期トレンドを可視化した。
| 年度 | 年平均気温(全国平均) | 最高気温(全国平均) |
|---|---|---|
| 2012 | 15.20℃ | 32.90℃ |
| 2015 | 15.86℃ | 31.14℃ |
| 2018 | 16.03℃ | 33.04℃ |
| 2020 | 16.20℃ | 33.79℃ |
| 2022 | 16.07℃ | 32.30℃ |
| 2023 | 16.80℃ | 34.00℃ |
時系列データのトレンド(単調増加・減少)を検定する方法として、スピアマン順位相関やMann-Kendall検定がある。OLSによるトレンド直線のあてはめも直感的に有用。
133 134 135 136 137 138 | fig3, ax3 = plt.subplots(figsize=(11, 5)) # 年平均気温の推移 ax3.plot(years_all, ts_temp_avg, color='#1565C0', linewidth=2.5, marker='o', markersize=7, label='年平均気温', zorder=4) ax3.fill_between(years_all, ts_temp_avg, alpha=0.15, color='#1565C0') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。ax.fill_between(...) — 2つの曲線で囲まれた領域を塗りつぶし。Lorenz曲線の格差面積などを可視化。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | # トレンド直線(OLS) z3 = np.polyfit(years_all, ts_temp_avg, 1) xs3 = np.array(years_all) ax3.plot(xs3, np.poly1d(z3)(xs3), color='#C62828', linewidth=1.8, linestyle='--', alpha=0.8, label=f'トレンド (傾き={z3[0]:.3f}℃/年)') # 最高気温の副軸 ax3b = ax3.twinx() ax3b.plot(years_all, ts_temp_max, color='#E65100', linewidth=2.0, marker='s', markersize=6, linestyle='-.', label='最高気温', zorder=3, alpha=0.85) ax3b.set_ylabel('最高気温(℃)', fontsize=11, color='#E65100') ax3b.tick_params(axis='y', labelcolor='#E65100') ax3.set_xlabel('年度', fontsize=12) ax3.set_ylabel('年平均気温(℃)', fontsize=12) ax3.set_title('全国平均気温の推移(2012-2023年度)\n' '47都道府県平均 — SSDSE-B-2026 実データ', fontsize=13, fontweight='bold') ax3.set_xticks(years_all) ax3.set_xticklabels([str(y) for y in years_all], rotation=30, fontsize=9) ax3.grid(True, alpha=0.3) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | # 凡例をまとめる lines1, labels1 = ax3.get_legend_handles_labels() lines2, labels2 = ax3b.get_legend_handles_labels() ax3.legend(lines1 + lines2, labels1 + labels2, fontsize=10, loc='upper left') # スピアマン相関のメモ ax3.text(0.98, 0.05, f'年平均気温トレンド\nρ={rho_ta:.3f}, p={p_ta:.3f}', transform=ax3.transAxes, fontsize=9, horizontalalignment='right', color='#333', bbox=dict(boxstyle='round,pad=0.4', facecolor='#E8F5E9', alpha=0.85)) plt.tight_layout() fig3.savefig(FIG_DIR + '2023_H5_3_fig3_timeseries.png', bbox_inches='tight', dpi=150) plt.close(fig3) print("図3保存: 2023_H5_3_fig3_timeseries.png") |
図3保存: 2023_H5_3_fig3_timeseries.png
np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。気温変数(年平均・最高・最低)、降水変数(降水日数・降水量)、高齢化率、保健医療費割合、病院密度の 相互相関をヒートマップで可視化した。
相関行列ヒートマップは多変数間の関係を一覧できる強力な探索ツール。多重共線性(変数間の高相関)を事前に確認することで、重回帰モデルの変数選択に活用できる。
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | var_labels = ['年平均気温', '最高気温', '最低気温', '降水日数', '降水量', '高齢化率', '保健医療費割合', '病院密度'] X_mat = np.column_stack([_ta, _tm, _tn, _rd, _rv, _ar, _hr, _hd]) # 欠損のある列を除外 valid_rows = np.all(np.isfinite(X_mat), axis=1) X_mat_clean = X_mat[valid_rows] n_vars = X_mat_clean.shape[1] corr_mat = np.zeros((n_vars, n_vars)) pval_mat = np.zeros((n_vars, n_vars)) for i in range(n_vars): for j in range(n_vars): r_ij, p_ij = stats.pearsonr(X_mat_clean[:, i], X_mat_clean[:, j]) corr_mat[i, j] = r_ij pval_mat[i, j] = p_ij fig4, ax4 = plt.subplots(figsize=(10, 8)) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。196 197 198 199 200 201 202 203 | # カラーマップ im = ax4.imshow(corr_mat, cmap='RdBu_r', vmin=-1, vmax=1, aspect='auto') plt.colorbar(im, ax=ax4, label='ピアソン相関係数', fraction=0.046, pad=0.04) ax4.set_xticks(range(n_vars)) ax4.set_yticks(range(n_vars)) ax4.set_xticklabels(var_labels, rotation=30, ha='right', fontsize=10) ax4.set_yticklabels(var_labels, fontsize=10) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。204 205 206 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 | # セルに値を表示 for i in range(n_vars): for j in range(n_vars): r_val = corr_mat[i, j] p_val = pval_mat[i, j] sig_star = '***' if p_val < 0.001 else '**' if p_val < 0.01 else '*' if p_val < 0.05 else '' text_color = 'white' if abs(r_val) > 0.6 else 'black' ax4.text(j, i, f'{r_val:.2f}{sig_star}', ha='center', va='center', fontsize=8.5, color=text_color, fontweight='bold' if sig_star else 'normal') ax4.set_title('相関ヒートマップ:気温・高齢化・医療変数(2022年度 47都道府県)\n' '* p<0.05 ** p<0.01 *** p<0.001', fontsize=12, fontweight='bold', pad=15) plt.tight_layout() fig4.savefig(FIG_DIR + '2023_H5_3_fig4_heatmap.png', bbox_inches='tight', dpi=150) plt.close(fig4) print("図4保存: 2023_H5_3_fig4_heatmap.png") print("\n" + "=" * 60) print("■ 全図の生成完了(4枚)") print("=" * 60) print(" fig1_temp_health.png : 最高気温 × 保健医療費割合 散布図") print(" fig2_aging_health.png : 高齢化率 × 保健医療費割合 散布図") print(" fig3_timeseries.png : 2012-2023年 全国平均気温トレンド") print(" fig4_heatmap.png : 相関ヒートマップ(7変数)") print() print(" データ:SSDSE-B-2026.csv 実データのみ使用(np.random 一切不使用)") |
図4保存: 2023_H5_3_fig4_heatmap.png ============================================================ ■ 全図の生成完了(4枚) ============================================================ fig1_temp_health.png : 最高気温 × 保健医療費割合 散布図 fig2_aging_health.png : 高齢化率 × 保健医療費割合 散布図 fig3_timeseries.png : 2012-2023年 全国平均気温トレンド fig4_heatmap.png : 相関ヒートマップ(7変数) データ:SSDSE-B-2026.csv 実データのみ使用(np.random 一切不使用)
{値:.2f}(小数2桁)、{値:,}(3桁区切り)、{値:>10}(右寄せ10桁)など、覚えると出力が一気に整います。保健医療費割合(健康負担の代理指標)を目的変数に、最高気温・高齢化率・降水量を説明変数とした OLS重回帰分析を行った。
| 変数 | 偏回帰係数 | 標準誤差 | t値 | p値 | 有意 |
|---|---|---|---|---|---|
| 切片 | 2.859 | 1.684 | 1.697 | 0.097 | n.s. |
| 最高気温(℃) | +0.115 | 0.045 | 2.589 | 0.013 | * |
| 高齢化率(%) | −0.054 | 0.021 | −2.493 | 0.017 | * |
| 降水量(mm) | +0.000 | 0.000 | 0.271 | 0.788 | n.s. |
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import matplotlib.patches as mpatches import numpy as np import pandas as pd 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 = os.path.normpath('html/figures') + os.sep 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} のように書式も指定できます。253 254 255 256 257 258 259 260 261 262 263 264 | df_2022 = df_all[df_all['SSDSE-B-2026'] == 2022].copy().reset_index(drop=True) print("=" * 60) print(f"■ 2022年度 都道府県数: N={len(df_2022)}") print("=" * 60) # 派生変数の計算 pop = df_2022['A1101'].clip(lower=1) # 総人口 elder = df_2022['A1303'] # 65歳以上人口 hospit = df_2022['I510120'] # 一般病院数 spend = df_2022['L3221'] # 消費支出 health = df_2022['L322106'] # 保健医療費 |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。265 266 267 268 269 270 271 272 | # 高齢化率(%) aging_rate = (elder / pop * 100).values # 保健医療費割合(%): 消費支出に占める保健医療費の割合 health_ratio = (health / spend * 100).values # 病院密度(人口1万人あたり病院数) hosp_density = (hospit / pop * 10000).values |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。273 274 275 276 277 278 | # 気温変数 temp_avg = df_2022['B4101'].values # 年平均気温 temp_max = df_2022['B4102'].values # 最高気温 temp_min = df_2022['B4103'].values # 最低気温 rain_days = df_2022['B4106'].values # 降水日数 rain_vol = df_2022['B4109'].values # 年降水量 |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。279 280 281 282 283 284 285 286 287 288 289 290 | # 都道府県名(Prefecture列に英語、日本語ラベルはRow0から) pref_names = df_2022['Prefecture'].values # 有効行(欠損除外) valid_mask = ( np.isfinite(temp_max) & np.isfinite(health_ratio) & np.isfinite(aging_rate) & np.isfinite(hosp_density) & np.isfinite(temp_avg) & np.isfinite(temp_min) & np.isfinite(rain_days) & np.isfinite(rain_vol) ) N = valid_mask.sum() print(f"有効都道府県数(欠損除外後): N={N}") |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。291 292 293 294 295 296 297 298 299 300 | # フィルタ済みデータ _tm = temp_max[valid_mask] _ta = temp_avg[valid_mask] _tn = temp_min[valid_mask] _rd = rain_days[valid_mask] _rv = rain_vol[valid_mask] _ar = aging_rate[valid_mask] _hr = health_ratio[valid_mask] _hd = hosp_density[valid_mask] _pn = pref_names[valid_mask] |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 | # 相関分析結果の出力 print("\n" + "=" * 60) print("■ 相関分析(2022年度 47都道府県)") print("=" * 60) print(f"\n {'変数ペア':<35} {'r':>8} {'p値':>10} {'有意':>6}") print(" " + "-" * 63) pairs = [ ('最高気温 × 保健医療費割合', _tm, _hr), ('年平均気温 × 保健医療費割合', _ta, _hr), ('高齢化率 × 保健医療費割合', _ar, _hr), ('最高気温 × 高齢化率', _tm, _ar), ('降水量 × 最高気温', _rv, _tm), ('降水日数 × 最高気温', _rd, _tm), ('病院密度 × 保健医療費割合', _hd, _hr), ] for label, x, y in pairs: r, p = stats.pearsonr(x, y) sig = '***' if p < 0.001 else '**' if p < 0.01 else '*' if p < 0.05 else 'n.s.' print(f" {label:<35} {r:>8.4f} {p:>10.4f} {sig:>6}") |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。322 323 324 325 326 327 328 329 | # 重回帰分析(保健医療費割合 を最高気温・高齢化率・降水量で説明) print("\n" + "=" * 60) print("■ 重回帰分析: 保健医療費割合 ~ 最高気温 + 高齢化率 + 降水量") print("=" * 60) X_reg = sm.add_constant(np.column_stack([_tm, _ar, _rv])) model = sm.OLS(_hr, X_reg).fit() print(model.summary2()) |
============================================================
■ 2022年度 都道府県数: N=47
============================================================
有効都道府県数(欠損除外後): N=47
============================================================
■ 相関分析(2022年度 47都道府県)
============================================================
変数ペア r p値 有意
---------------------------------------------------------------
最高気温 × 保健医療費割合 0.3881 0.0070 **
年平均気温 × 保健医療費割合 0.4090 0.0043 **
高齢化率 × 保健医療費割合 -0.3792 0.0086 **
最高気温 × 高齢化率 -0.1359 0.3623 n.s.
降水量 × 最高気温 0.0133 0.9293 n.s.
降水日数 × 最高気温 -0.5103 0.0002 ***
病院密度 × 保健医療費割合 0.0142 0.9244 n.s.
============================================================
■ 重回帰分析: 保健医療費割合 ~ 最高気温 + 高齢化率 + 降水量
============================================================
Results: Ordinary least squares
================================================================
Model: OLS Adj. R-squared: 0.209
Dependent Variable: y AIC: 66.3862
Date: 2026-05-18 11:24 BIC: 73.7868
No. Observations: 47 Log-Likelihood: -29.193
Df Model: 3 F-statistic: 5.048
Df Residuals: 43 Prob (F-statistic): 0.00439
R-squared: 0.260 Scale: 0.22165
------------------------------------------------------------------
Coef. Std.Err. t P>|t| [0.025 0.975]
------------------------------------------------------------------
const 2.8594 1.6845 1.6975 0.0968 -0.5376 6.2565
x1 0.1153 0.0445 2.5888 0.0131 0.0255 0.2051
x2 -0.0535 0.0215 -2.4933 0.0166 -0.0968 -0.0102
x3 0.0000 0.0001 0.2712 0.7875 -0.0002 0.0003
----------------------------------------------------------------
Omnibus: 0.039 Durbin-Watson: 2.171
Prob(Omnibus): 0.981 Jarque-Bera (JB): 0.178
Skew: 0.060 Prob(JB): 0.915
Kurtosis: 2.723 Condition No.: 40198
================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the
errors is correctly specified.
[2] The condition number is large, 4.02e+04. This might indicate
that there are strong multicollinearity or other numerical
problems.sm.add_constant(X) — 切片項(定数1の列)を先頭に追加。statsmodelsで必須。sm.OLS(y, X).fit() — 最小二乗法でモデルを推定。model.params, model.pvalues, model.conf_int() で結果取得。np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。| 学習ポイント | 内容 | 実用例 |
|---|---|---|
| 相関分析 | ピアソン相関係数・無相関検定 | 気温×医療費の関係を定量化 |
| 重回帰分析 | 複数変数を同時に制御した効果推定 | 気温の純粋な影響を高齢化率から分離 |
| 時系列分析 | スピアマン相関によるトレンド検定 | 気温上昇の統計的有意性を確認 |
| データ可視化 | 散布図・ヒートマップ・時系列グラフ | 多次元の相関構造を一目で把握 |
| 代理指標の活用 | 目的の統計が無い場合の工夫 | 熱中症搬送数の代わりに医療費割合を使用 |
| データ | 出典 | 備考 |
|---|---|---|
| SSDSE-B 都道府県データ | 独立行政法人 統計センター(SSDSE) | 47都道府県 × 2012-2023年 |
| 気温データ(B4101, B4102, B4103) | 気象庁 気象統計情報(SSDSE経由) | 年平均・最高・最低気温 |
| 消費支出データ(L3221, L322106) | 総務省 家計調査(SSDSE経由) | 二人以上の世帯 |
| 人口・高齢化データ(A1101, A1303) | 総務省 住民基本台帳(SSDSE経由) | 65歳以上人口比率 |
本コードはSSDSE-B-2026.csv の実データのみを使用しています(np.random等の合成データ生成は一切使用していません)。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。