このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
大腸がんは日本人の罹患数が多いがんの一つであり、食生活・肥満・飲酒・運動不足など生活習慣との関連が多くの疫学研究で指摘されている。本研究は、公的統計データ(SSDSE-B)を用いて、大腸がんリスクと関連する生活習慣・経済環境・高齢化の影響を都道府県レベルで探索的に分析し、「罹患しにくい生活」への提案を行った。
まず「大腸がん罹患要因の探究と罹患しにくい生活の提案」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。
SSDSE-B 相関分析 散布図 外れ値分析 探索的データ解析
SSDSE(社会・人口統計体系)-B の2022年度データ(47都道府県)を使用。消費支出の内訳科目と人口関連変数から各指標を算出した。
| カテゴリ | 変数名 | 算出方法 | 大腸がんリスクとの想定関連 |
|---|---|---|---|
| 高齢化 | 高齢化率 (%) | 65歳以上人口 ÷ 総人口 × 100 | 高齢者は罹患リスクが高い |
| 食生活 | 食料費割合 (%) | 食料費 ÷ 消費支出 × 100 | 食費の比率(食生活の量的代理) |
| 余暇・飲酒代理 | 教養娯楽費割合 (%) | 教養娯楽費 ÷ 消費支出 × 100 | 娯楽支出(飲酒・外食活動の代理) |
| 光熱・生活環境 | 光熱・水道費割合 (%) | 光熱・水道費 ÷ 消費支出 × 100 | 寒冷地・農村環境の代理 |
| 被服・生活水準 | 被服費割合 (%) | 被服・履物費 ÷ 消費支出 × 100 | 都市型生活水準の代理 |
| 経済水準 | 消費支出(対数) | log(消費支出) | 所得・経済的豊かさの代理 |
| 医療アクセス | 一般診療所密度(万対) | 一般診療所数 ÷ 総人口 × 10000 | 医療アクセスが良い → 発見・受診率上昇 |
| 口腔衛生 | 歯科診療所密度(万対) | 歯科診療所数 ÷ 総人口 × 10000 | 口腔衛生・健康意識の代理 |
| 出生率 | 合計特殊出生率 | SSDSE-B 直接値 | ライフスタイル・若年人口構成の代理 |
1 2 3 4 5 6 7 8 9 10 | import os import warnings import numpy as np import pandas as pd import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from scipy import stats warnings.filterwarnings('ignore') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。matplotlib.use('Agg') — グラフを画面表示せずファイルに保存するためのおまじない。f"...{x}..." はf-string。文字列の中に {変数} と書くだけで埋め込めて、{x:.2f} のように書式も指定できます。11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # ── パス設定 ────────────────────────────────────────────────────────── DATA_DIR = 'data/raw' FIG_DIR = 'html/figures' os.makedirs(FIG_DIR, exist_ok=True) plt.rcParams.update({ 'font.family': 'Hiragino Sans', 'axes.unicode_minus': False, 'figure.dpi': 150, 'axes.spines.top': False, 'axes.spines.right': False, }) df_raw = pd.read_csv( os.path.join(DATA_DIR, 'SSDSE-B-2026.csv'), encoding='cp932', header=1 ) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。os.makedirs('html/figures', exist_ok=True) — 図の保存先フォルダを作る(既にあってもOK)。pd.read_csv(...) でCSVを読み込みます。encoding='cp932' は日本語Windows由来の文字コード、header=1 は「2行目を列名として使う」。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。28 29 30 31 32 33 34 35 36 | # 2022年度・都道府県コードのみ抽出(47都道府県) df = df_raw[ (df_raw['年度'] == 2022) & df_raw['地域コード'].str.match(r'^R\d{5}$', na=False) ].copy().reset_index(drop=True) assert len(df) == 47, f"Expected 47 rows, got {len(df)}" print(f"=== データ読み込み完了 ===") print(f" 年度: 2022, 都道府県数: {len(df)}") |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df['地域コード'].str.match(r'^R\d{5}', ...) — 正規表現で「R+数字5桁」の行(47都道府県)だけTrueにし、真偽値で行をフィルタ。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。37 38 39 40 41 42 43 44 45 46 47 | # ── 数値変換 ───────────────────────────────────────────────────────── num_cols = [ '総人口', '65歳以上人口', '合計特殊出生率', '消費支出(二人以上の世帯)', '食料費(二人以上の世帯)', '保健医療費(二人以上の世帯)', '教養娯楽費(二人以上の世帯)', '光熱・水道費(二人以上の世帯)', '被服及び履物費(二人以上の世帯)', '交通・通信費(二人以上の世帯)', '教育費(二人以上の世帯)', '歯科診療所数', '一般診療所数', ] for c in num_cols: df[c] = pd.to_numeric(df[c], errors='coerce') |
=== データ読み込み完了 === 年度: 2022, 都道府県数: 47
[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。11の説明変数それぞれについて、保健医療費割合との Pearson 相関係数と p 値を算出し、絶対値の大きい順に図示した。
| 変数 | 相関係数 r | p 値 | 有意性 | 解釈 |
|---|---|---|---|---|
| 光熱・水道費割合 | −0.602 | <0.001 | ** | 光熱費割合が高い地域(寒冷・農村)は保健医療費割合が低い |
| 被服費割合 | +0.423 | 0.003 | ** | 被服費が高い(都市型・高生活水準)地域で保健医療費割合が高い |
| 交通・通信費割合 | −0.401 | 0.005 | ** | 交通費割合が高い地域(地方・農村)で保健医療費割合が低い |
| 高齢化率 | −0.379 | 0.009 | ** | 高齢化が進んだ地域で保健医療費割合が低い(逆説的相関) |
| 消費支出(対数) | +0.311 | 0.034 | * | 消費水準が高い(富裕)地域ほど保健医療費割合が高い |
| 歯科診療所密度 | +0.266 | 0.070 | 傾向 | (有意傾向)歯科診療所が多い地域はやや保健医療費割合が高い |
| 教養娯楽費割合 | +0.184 | 0.215 | ns | 有意な関連なし |
| 一般診療所密度 | +0.180 | 0.225 | ns | 有意な関連なし |
| 教育費割合 | +0.174 | 0.242 | ns | 有意な関連なし |
| 食料費割合 | −0.103 | 0.492 | ns | 有意な関連なし(食費単独では判断困難) |
| 合計特殊出生率 | +0.047 | 0.753 | ns | 関連なし |
N=47(都道府県)の場合、|r|≥0.29 程度で p<0.05 となる。「有意」であっても相関関係であって因果関係ではない。交絡変数(第三の変数)の影響も常に考慮する必要がある。
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 | sorted_items = sorted(corr_results.items(), key=lambda x: abs(x[1]['r']), reverse=True) names_sorted = [x[0] for x in sorted_items] r_sorted = [x[1]['r'] for x in sorted_items] p_sorted = [x[1]['p'] for x in sorted_items] colors_bar = ['#C62828' if p < 0.05 else '#90A4AE' for p in p_sorted] fig, ax = plt.subplots(figsize=(9, 6)) bars = ax.barh(range(len(names_sorted)), r_sorted, color=colors_bar, alpha=0.85, height=0.65) ax.set_yticks(range(len(names_sorted))) ax.set_yticklabels(names_sorted, fontsize=10) ax.axvline(0, color='black', lw=1.0) ax.set_xlabel('Pearson 相関係数 r', fontsize=11) ax.set_title('各指標と保健医療費割合の相関係数\n(赤:p<0.05有意、灰:非有意)', fontsize=13, fontweight='bold') ax.set_xlim(-1, 1) for i, (bar, r, p) in enumerate(zip(bars, r_sorted, p_sorted)): xpos = bar.get_width() + (0.02 if r >= 0 else -0.02) ha = 'left' if r >= 0 else 'right' label = f'r={r:.2f}{"*" if p < 0.05 else ""}' ax.text(xpos, i, label, va='center', fontsize=8.5, ha=ha) import matplotlib.patches as mpatches sig_patch = mpatches.Patch(color='#C62828', alpha=0.85, label='有意 (p<0.05)') ns_patch = mpatches.Patch(color='#90A4AE', alpha=0.85, label='非有意') ax.legend(handles=[sig_patch, ns_patch], fontsize=9, loc='lower right') plt.tight_layout() fig1_path = os.path.join(FIG_DIR, '2023_H2_fig1_corr.png') plt.savefig(fig1_path, bbox_inches='tight') plt.close() print(f"\nFigure 1 saved: {fig1_path}") |
Figure 1 saved: html/figures/2023_H2_fig1_corr.png
import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。高齢化が進むほど大腸がん罹患リスクが上昇すると予想されるが、都道府県データでは逆方向の相関(r=−0.379)が観察された。この「逆説的な相関」の背景に外れ値の影響がないか、2本の回帰線で確認する。
| モデル | 相関係数 r | p 値 | 有意性 | 備考 |
|---|---|---|---|---|
| 全47都道府県 | −0.379 | 0.009 | ** | — |
| 京都府除外(46都道府県) | −0.375 | 0.010 | ** | 外れ値の影響は軽微 |
外れ値1点が相関係数を大きく動かすことがある。「全データ」と「外れ値除外」の2本の回帰線を重ねて描くことで、外れ値の影響を視覚的に確認できる。2本の線が大きくずれていれば外れ値の影響が大きい。
83 84 85 86 87 88 89 90 | x2 = aging_rate y2 = health_share mask_valid = ~(np.isnan(x2) | np.isnan(y2)) x2v, y2v = x2[mask_valid], y2[mask_valid] pref_v = pref[mask_valid] # 外れ値マスク(保健医療費割合が最高の都道府県) is_outlier = (pref_v == outlier_pref) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。91 92 93 94 95 96 97 98 | # 全データ回帰 slope_all, intercept_all, r_all, p_all, _ = stats.linregress(x2v, y2v) # 外れ値除外回帰 xno = x2v[~is_outlier] yno = y2v[~is_outlier] slope_no, intercept_no, r_no, p_no, _ = stats.linregress(xno, yno) fig, ax = plt.subplots(figsize=(8, 6)) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。stats.linregress(x, y) — 単回帰の傾き・切片・r値・p値・標準誤差を返します。使わない値は _ で受け取り。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。99 100 101 102 103 104 105 106 107 108 109 | # 通常の点 ax.scatter(x2v[~is_outlier], y2v[~is_outlier], color='#1565C0', alpha=0.7, s=55, zorder=3, label='都道府県') # 外れ値の点 ax.scatter(x2v[is_outlier], y2v[is_outlier], color='#C62828', s=120, zorder=5, marker='*', label=f'外れ値:{outlier_pref}') for xi, yi, pi in zip(x2v[is_outlier], y2v[is_outlier], pref_v[is_outlier]): ax.annotate(pi, (xi, yi), textcoords='offset points', xytext=(6, 4), fontsize=9, color='#C62828', fontweight='bold') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | # 回帰線(全データ) x_line = np.linspace(x2v.min(), x2v.max(), 200) ax.plot(x_line, slope_all * x_line + intercept_all, color='#1565C0', lw=2, ls='-', label=f'全都道府県 (r={r_all:+.3f}, p={p_all:.3f})') # 回帰線(外れ値除外) ax.plot(x_line, slope_no * x_line + intercept_no, color='#E65100', lw=2, ls='--', label=f'外れ値除外 (r={r_no:+.3f}, p={p_no:.3f})') ax.set_xlabel('高齢化率 (%)', fontsize=12) ax.set_ylabel('保健医療費割合 (%)', fontsize=12) ax.set_title('高齢化率と保健医療費割合の関係\n(外れ値の影響を確認)', fontsize=13, fontweight='bold') ax.legend(fontsize=9) plt.tight_layout() fig2_path = os.path.join(FIG_DIR, '2023_H2_fig2_aging.png') plt.savefig(fig2_path, bbox_inches='tight') plt.close() print(f"Figure 2 saved: {fig2_path}") print(f" 全データ: r={r_all:+.4f} p={p_all:.4f}") print(f" 外れ値除外: r={r_no:+.4f} p={p_no:.4f}") |
Figure 2 saved: html/figures/2023_H2_fig2_aging.png 全データ: r=-0.3792 p=0.0086 外れ値除外: r=-0.3751 p=0.0102
fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。大腸がんの主要リスク因子として食生活が挙げられる。食料費割合(食費の消費支出に占める割合)を食生活の代理指標として分析した。
p>0.05(統計的に有意でない)は「関係がない」ではなく、「このデータ・このサンプルサイズでは関係が検出できなかった」を意味する。N=47では |r|≥0.29 程度が検出の目安であり、それより小さい効果量は見逃される可能性がある。
135 136 137 138 139 140 141 142 143 | x3 = food_share y3 = health_share mask3 = ~(np.isnan(x3) | np.isnan(y3)) x3v, y3v, pref3 = x3[mask3], y3[mask3], pref[mask3] slope3, intercept3, r3, p3, _ = stats.linregress(x3v, y3v) fig, ax = plt.subplots(figsize=(8, 6)) ax.scatter(x3v, y3v, color='#2E7D32', alpha=0.75, s=55, zorder=3) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。stats.linregress(x, y) — 単回帰の傾き・切片・r値・p値・標準誤差を返します。使わない値は _ で受け取り。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | # 注目点(最高保健医療費) for xi, yi, pi in zip(x3v, y3v, pref3): if pi in [outlier_pref, pref[idx_min]]: ax.annotate(pi, (xi, yi), textcoords='offset points', xytext=(6, 3), fontsize=8.5, color='#C62828', fontweight='bold') ax.scatter([xi], [yi], color='#C62828', s=80, zorder=5) x_line3 = np.linspace(x3v.min(), x3v.max(), 200) ax.plot(x_line3, slope3 * x_line3 + intercept3, color='#2E7D32', lw=2, label=f'回帰直線 (r={r3:+.3f}, p={p3:.3f})') ax.set_xlabel('食料費割合 (%)', fontsize=12) ax.set_ylabel('保健医療費割合 (%)', fontsize=12) ax.set_title('食料費割合と保健医療費割合の関係\n(食生活と疾病負担の代理変数)', fontsize=13, fontweight='bold') ax.legend(fontsize=10) plt.tight_layout() fig3_path = os.path.join(FIG_DIR, '2023_H2_fig3_food.png') plt.savefig(fig3_path, bbox_inches='tight') plt.close() print(f"Figure 3 saved: {fig3_path}") print(f" 食料費割合 vs 保健医療費割合: r={r3:+.4f} p={p3:.4f}") |
Figure 3 saved: html/figures/2023_H2_fig3_food.png 食料費割合 vs 保健医療費割合: r=-0.1027 p=0.4921
fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。消費支出は経済的豊かさの代理指標であり、医療へのアクセス意欲や生活水準を反映する。全47都道府県のラベルを付した散布図で地域差を視覚化した。
散布図に個々のデータポイントのラベルを付けることで、回帰直線から大きく外れた観察値(残差が大きい点)をすぐに特定できる。これは EDA(Exploratory Data Analysis)の基本技法。
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | pop = df['総人口'].values.clip(1) spend = df['消費支出(二人以上の世帯)'].values.astype(float).clip(1) # 目的変数:保健医療費割合(%)= 保健医療費 / 消費支出 × 100 health_share = df['保健医療費(二人以上の世帯)'].values / spend * 100 # 説明変数群 aging_rate = df['65歳以上人口'].values / pop * 100 # 高齢化率(%) food_share = df['食料費(二人以上の世帯)'].values / spend * 100 # 食料費割合(%) leisure_share= df['教養娯楽費(二人以上の世帯)'].values / spend * 100 # 教養娯楽費割合(%) heat_share = df['光熱・水道費(二人以上の世帯)'].values / spend * 100 # 光熱・水道費割合(%) cloth_share = df['被服及び履物費(二人以上の世帯)'].values / spend * 100 # 被服費割合(%) transp_share = df['交通・通信費(二人以上の世帯)'].values / spend * 100 # 交通・通信費割合(%) edu_share = df['教育費(二人以上の世帯)'].values / spend * 100 # 教育費割合(%) tfr = df['合計特殊出生率'].values.astype(float) # 合計特殊出生率 dental_density = df['歯科診療所数'].values / pop * 10000 # 歯科診療所密度(人口1万対) clinic_density = df['一般診療所数'].values / pop * 10000 # 一般診療所密度(人口1万対) log_spend = np.log(spend) # 消費支出(対数) pref = df['都道府県'].values |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | predictors = { '高齢化率 (%)': aging_rate, '食料費割合 (%)': food_share, '教養娯楽費割合 (%)': leisure_share, '光熱・水道費割合 (%)': heat_share, '被服費割合 (%)': cloth_share, '交通・通信費割合 (%)': transp_share, '教育費割合 (%)': edu_share, '合計特殊出生率': tfr, '歯科診療所密度(万対)': dental_density, '一般診療所密度(万対)': clinic_density, '消費支出(対数)': log_spend, } print("\n=== Pearson 相関係数(vs 保健医療費割合) ===") corr_results = {} for name, vals in predictors.items(): mask = ~(np.isnan(vals) | np.isnan(health_share)) if mask.sum() < 5: continue r, p = stats.pearsonr(vals[mask], health_share[mask]) corr_results[name] = {'r': r, 'p': p} sig = '**' if p < 0.01 else ('*' if p < 0.05 else 'ns') print(f" {name:25s} r={r:+.4f} p={p:.4f} {sig}") |
=== Pearson 相関係数(vs 保健医療費割合) === 高齢化率 (%) r=-0.3792 p=0.0086 ** 食料費割合 (%) r=-0.1027 p=0.4921 ns 教養娯楽費割合 (%) r=+0.1842 p=0.2152 ns 光熱・水道費割合 (%) r=-0.6019 p=0.0000 ** 被服費割合 (%) r=+0.4227 p=0.0031 ** 交通・通信費割合 (%) r=-0.4006 p=0.0053 ** 教育費割合 (%) r=+0.1741 p=0.2420 ns 合計特殊出生率 r=+0.0471 p=0.7534 ns 歯科診療所密度(万対) r=+0.2664 p=0.0703 ns 一般診療所密度(万対) r=+0.1804 p=0.2250 ns 消費支出(対数) r=+0.3105 p=0.0337 *
stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。213 214 215 216 217 218 219 220 221 | idx_max = np.argmax(health_share) idx_min = np.argmin(health_share) outlier_idx = idx_max # 最高値を外れ値として扱う outlier_pref = pref[outlier_idx] print(f"\n=== 保健医療費割合の外れ値 ===") print(f" 最高: {pref[idx_max]} ({health_share[idx_max]:.2f}%)") print(f" 最低: {pref[idx_min]} ({health_share[idx_min]:.2f}%)") print(f" 全体平均: {health_share.mean():.2f}% SD: {health_share.std():.2f}%") |
=== 保健医療費割合の外れ値 === 最高: 京都府 (6.13%) 最低: 青森県 (3.77%) 全体平均: 4.96% SD: 0.52%
[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。222 223 224 225 226 227 228 229 230 | x4 = spend / 1000 # 千円単位 y4 = health_share mask4 = ~(np.isnan(x4) | np.isnan(y4)) x4v, y4v, pref4 = x4[mask4], y4[mask4], pref[mask4] slope4, intercept4, r4, p4, _ = stats.linregress(x4v, y4v) fig, ax = plt.subplots(figsize=(11, 7)) ax.scatter(x4v, y4v, color='#6A1B9A', alpha=0.7, s=50, zorder=3) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。stats.linregress(x, y) — 単回帰の傾き・切片・r値・p値・標準誤差を返します。使わない値は _ で受け取り。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 | # 全都道府県ラベル(小さめ) for xi, yi, pi in zip(x4v, y4v, pref4): short = pi.replace('都', '').replace('道', '').replace('府', '').replace('県', '') color = '#C62828' if pi == outlier_pref else '#333333' weight = 'bold' if pi == outlier_pref else 'normal' ax.text(xi, yi + 0.04, short, fontsize=6.5, ha='center', color=color, fontweight=weight) x_line4 = np.linspace(x4v.min(), x4v.max(), 200) ax.plot(x_line4, slope4 * x_line4 + intercept4, color='#6A1B9A', lw=2, label=f'回帰直線 (r={r4:+.3f}, p={p4:.3f})') ax.set_xlabel('消費支出(千円/月・二人以上世帯)', fontsize=12) ax.set_ylabel('保健医療費割合 (%)', fontsize=12) ax.set_title('消費支出と保健医療費割合の関係(都道府県別)\n' '(赤字:外れ値都道府県)', fontsize=13, fontweight='bold') ax.legend(fontsize=10) plt.tight_layout() fig4_path = os.path.join(FIG_DIR, '2023_H2_fig4_spend.png') plt.savefig(fig4_path, bbox_inches='tight') plt.close() print(f"Figure 4 saved: {fig4_path}") print(f" 消費支出 vs 保健医療費割合: r={r4:+.4f} p={p4:.4f}") |
Figure 4 saved: html/figures/2023_H2_fig4_spend.png 消費支出 vs 保健医療費割合: r=+0.3055 p=0.0368
fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。257 258 259 260 261 262 263 264 265 266 267 | print("\n=== 分析サマリー ===") print(f" 目的変数: 保健医療費割合(保健医療費/消費支出×100)") print(f" データ: SSDSE-B-2026.csv 2022年度 47都道府県") print(f" 外れ値(最高): {pref[idx_max]} {health_share[idx_max]:.2f}%") print(f" 外れ値(最低): {pref[idx_min]} {health_share[idx_min]:.2f}%") print(f" 平均: {health_share.mean():.2f}% SD: {health_share.std():.2f}%") print("\n上位相関変数(絶対値):") for name, res in sorted_items[:5]: sig = '有意' if res['p'] < 0.05 else '非有意' print(f" {name:25s} r={res['r']:+.4f} p={res['p']:.4f} ({sig})") print("\n分析完了。html/figures/ に図を保存しました。") |
=== 分析サマリー === 目的変数: 保健医療費割合(保健医療費/消費支出×100) データ: SSDSE-B-2026.csv 2022年度 47都道府県 外れ値(最高): 京都府 6.13% 外れ値(最低): 青森県 3.77% 平均: 4.96% SD: 0.52% 上位相関変数(絶対値): 光熱・水道費割合 (%) r=-0.6019 p=0.0000 (有意) 被服費割合 (%) r=+0.4227 p=0.0031 (有意) 交通・通信費割合 (%) r=-0.4006 p=0.0053 (有意) 高齢化率 (%) r=-0.3792 p=0.0086 (有意) 消費支出(対数) r=+0.3105 p=0.0337 (有意) 分析完了。html/figures/ に図を保存しました。
np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。SSDSE-B の2022年度47都道府県データを用い、保健医療費割合(疾病負担プロキシ)との相関分析を行った結果:
| データ・資料 | 出典 |
|---|---|
| SSDSE-B 都道府県データ(2022年度) | 統計センター SSDSE(社会・人口統計体系) |
| 消費支出・保健医療費データ | 総務省統計局 家計調査(SSDSE-B収録) |
| 人口・高齢化率データ | 総務省統計局 住民基本台帳(SSDSE-B収録) |
本教育用コードはSSDSE-B実データのみを使用(合成データ・np.random 不使用)。2022年度47都道府県データより算出。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。