このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
日本では地域ごとに医療機関数や医師数の分布が大きく異なる。地方圏では医療資源が不足し、都市部では相対的に充実しているという格差は「医療過疎」として社会問題化している。一方で、診療所密度は必ずしも大都市が高いわけではなく、地方の高齢化率が高い地域でも多くの医療機関が存在するという逆説的な現象も見られる。
まず「医療資源の地域格差医療機関・医師数の分布と決定要因分析」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。
本研究は、SSDSE-B(都道府県別パネルデータ)を用いて、医療機関密度(人口1万人当たりの医療機関数)の都道府県間格差を定量化し、その決定要因を分析する。高齢化率・消費支出・保健医療費を説明変数とするOLS回帰によって、需要側・供給側の両面から医療資源の立地メカニズムを考察する。
SSDSE-B 相関分析 OLS回帰 ジニ係数的アプローチ 地域比較
SSDSE-B-2026(社会・人口統計体系 都道府県データ)を使用する。全47都道府県 × 2012〜2023年度(12年間)の計564レコードを分析対象とする。
| 変数名 | SSDSE-Bコード | 説明 | 単位 |
|---|---|---|---|
| 一般病院数 | I510120 | 一般病院(病床20床以上)の数 | 施設数 |
| 一般診療所数 | I5102 | 一般診療所(無床・19床以下)の数 | 施設数 |
| 歯科診療所数 | I5103 | 歯科診療所の数 | 施設数 |
| 総人口 | A1101 | 都道府県の総人口 | 人 |
| 65歳以上人口 | A1303 | 高齢者(65歳以上)人口 | 人 |
| 消費支出(二人以上世帯) | L3221 | 家計の月平均消費支出 | 円 |
| 保健医療費(二人以上世帯) | L322106 | 保健・医療への月平均支出 | 円 |
人口規模の大きい都道府県ほど医療機関の絶対数も多くなるため、単純な施設数の比較は意味をなさない。そこで人口1万人当たりの施設数(密度)に変換して比較する。
病院密度のジニ係数(0.213)は診療所密度(0.080)の約2.7倍であり、病院の立地格差が診療所より大幅に大きいことを示している。
東京都の診療所数は全国最多だが、「人口当たり」で見ると徳島県・長崎県などが上位に入る。絶対数ではなく密度(人口標準化)で比較することで初めて公平な地域比較が可能になる。
1 2 3 4 5 6 7 8 9 10 11 | import os import warnings import numpy as np import pandas as pd import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import matplotlib.ticker as mticker from scipy import stats warnings.filterwarnings('ignore') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。matplotlib.use('Agg') — グラフを画面表示せずファイルに保存するためのおまじない。f"...{x}..." はf-string。文字列の中に {変数} と書くだけで埋め込めて、{x:.2f} のように書式も指定できます。12 13 14 15 16 17 18 19 20 21 22 23 | # ── パス設定 ────────────────────────────────────────────────────────────────── FIG_DIR = 'html/figures' DATA_B = 'data/raw/SSDSE-B-2026.csv' 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, }) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。os.makedirs('html/figures', exist_ok=True) — 図の保存先フォルダを作る(既にあってもOK)。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。24 25 26 27 28 29 30 | # ── データ読み込み ──────────────────────────────────────────────────────────── raw = pd.read_csv(DATA_B, encoding='cp932', header=0) # 行0はJapanese label row; 実データは行1以降 df_all = raw.iloc[1:].copy() df_all.columns = raw.columns YEAR_COL = df_all.columns[0] # 'SSDSE-B-2026' |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。pd.read_csv(...) でCSVを読み込みます。encoding='cp932' は日本語Windows由来の文字コード、header=1 は「2行目を列名として使う」。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。31 32 33 34 35 36 37 38 39 | # 都道府県コードのみ(R01000〜R47000) df_all = df_all[df_all['Code'].str.match(r'^R\d{5}$')].copy() # 数値変換 NUM_COLS = ['I510120', 'I5102', 'I5103', 'A1101', 'A1303', 'L3221', 'L322106'] for col in NUM_COLS: df_all[col] = pd.to_numeric(df_all[col], errors='coerce') df_all['year'] = df_all[YEAR_COL].astype(int) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df['地域コード'].str.match(r'^R\d{5}', ...) — 正規表現で「R+数字5桁」の行(47都道府県)だけTrueにし、真偽値で行をフィルタ。.astype(int) — 列を整数に変換(年度などを数値比較するため)。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。40 41 42 43 44 45 46 47 48 49 | # ── 派生指標の計算 ──────────────────────────────────────────────────────────── df_all['病院密度'] = df_all['I510120'] / df_all['A1101'] * 10000 df_all['診療所密度'] = df_all['I5102'] / df_all['A1101'] * 10000 df_all['歯科密度'] = df_all['I5103'] / df_all['A1101'] * 10000 df_all['医療機関密度_総合'] = (df_all['I510120'] + df_all['I5102']) / df_all['A1101'] * 10000 df_all['高齢化率'] = df_all['A1303'] / df_all['A1101'] * 100 df_all['消費支出_log'] = np.log(df_all['L3221'].clip(lower=1)) df_all['保健医療費_千円'] = df_all['L322106'] / 1000 print(f"読み込み完了: {len(df_all)}レコード, {df_all['year'].nunique()}年度, {df_all['Prefecture'].nunique()}都道府県") |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | # 2022年断面データ d22 = df_all[df_all['year'] == 2022].copy() d22 = d22.dropna(subset=['病院密度', '診療所密度', '歯科密度', '高齢化率']).sort_values('医療機関密度_総合', ascending=False) def gini_coefficient(values): """ローレンツ曲線に基づくジニ係数を計算する。""" v = np.sort(np.array(values, dtype=float)) n = len(v) idx = np.arange(1, n + 1) return (2 * np.dot(idx, v)) / (n * v.sum()) - (n + 1) / n g_hosp = gini_coefficient(d22['病院密度'].dropna()) g_clin = gini_coefficient(d22['診療所密度'].dropna()) g_dent = gini_coefficient(d22['歯科密度'].dropna()) g_total = gini_coefficient(d22['医療機関密度_総合'].dropna()) print(f"\nジニ係数 (2022年, 47都道府県):") print(f" 病院密度: {g_hosp:.4f}") print(f" 診療所密度: {g_clin:.4f}") print(f" 歯科密度: {g_dent:.4f}") print(f" 医療機関密度_総合: {g_total:.4f}") |
読み込み完了: 564レコード, 12年度, 47都道府県 ジニ係数 (2022年, 47都道府県): 病院密度: 0.2127 診療所密度: 0.0796 歯科密度: 0.0671 医療機関密度_総合: 0.0796
gini(arr) — Gini係数(0=完全平等、1=完全不平等)を計算。ソート → 累積和 → 公式という単純実装。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。2022年の47都道府県について、医療機関密度(病院・診療所・歯科の3種)を積み上げた棒グラフで比較する。医療機関密度_総合(病院+診療所)の高い順に並べている。
| 順位 | 都道府県 | 病院密度 | 診療所密度 | 歯科密度 |
|---|---|---|---|---|
| 1 | 高知県 | 1.598 | 7.811 | 5.118 |
| 2 | 徳島県 | 1.293 | 9.986 | 5.994 |
| 3 | 鹿児島県 | 1.235 | 8.861 | 5.086 |
| 4 | 大分県 | 1.138 | 8.690 | 4.734 |
| 5 | 宮崎県 | 1.093 | 8.726 | 4.639 |
| 45 | 埼玉県 | 0.272 | 6.209 | 4.266 |
| 46 | 神奈川県 | 0.268 | 6.437 | 4.702 |
| 47 | 東京都 | 0.246 | 9.021 | 6.183 |
単位:施設数 / 人口1万人。出典:SSDSE-B-2026(2022年度データ)。
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | fig1, ax1 = plt.subplots(figsize=(14, 8)) prefs = d22['Prefecture'].values hosp_v = d22['病院密度'].values clin_v = d22['診療所密度'].values dent_v = d22['歯科密度'].values x = np.arange(len(prefs)) bar_w = 0.72 b1 = ax1.bar(x, hosp_v, bar_w, label='一般病院', color='#1565C0', alpha=0.9) b2 = ax1.bar(x, clin_v, bar_w, bottom=hosp_v, label='一般診療所', color='#42A5F5', alpha=0.9) b3 = ax1.bar(x, dent_v, bar_w, bottom=hosp_v + clin_v, label='歯科診療所', color='#E65100', alpha=0.85) ax1.set_xticks(x) ax1.set_xticklabels(prefs, rotation=90, fontsize=8.5) ax1.set_ylabel('人口1万人当たり医療機関数(機関)', fontsize=11) ax1.set_title('Fig 1|都道府県別 医療機関密度(2022年)\n病院・診療所・歯科の積み上げ', fontsize=13, fontweight='bold', pad=14) ax1.legend(loc='upper right', fontsize=10) ax1.yaxis.set_major_formatter(mticker.FormatStrFormatter('%.1f')) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。91 92 93 94 95 96 97 98 99 100 101 | # 全国平均線 nat_avg = (d22['医療機関密度_総合'] + d22['歯科密度']).mean() ax1.axhline(nat_avg, color='gray', linestyle='--', linewidth=1.2, alpha=0.8) ax1.text(len(prefs) - 0.5, nat_avg + 0.08, f'全国平均\n{nat_avg:.2f}', fontsize=8.5, color='gray', ha='right') fig1.tight_layout() fig1_path = os.path.join(FIG_DIR, '2021_U4_fig1_ranking.png') fig1.savefig(fig1_path, dpi=150, bbox_inches='tight') plt.close(fig1) print(f"\nFig1 保存: {fig1_path}") |
Fig1 保存: html/figures/2021_U4_fig1_ranking.png
ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。高齢化率(65歳以上人口比率)と医療機関密度_総合(病院+診療所)の関係を都道府県ラベル付きの散布図で確認する。もし高齢者の多い地域に医療機関が集まるならば、正の相関が見られるはずである。
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 132 133 134 135 136 137 138 139 140 141 142 | d22_sc = d22.dropna(subset=['高齢化率', '医療機関密度_総合']) fig2, ax2 = plt.subplots(figsize=(10, 7)) # 地域区分(総務省8地域) region_map = { '北海道': '北海道', '青森県': '東北', '岩手県': '東北', '宮城県': '東北', '秋田県': '東北', '山形県': '東北', '福島県': '東北', '茨城県': '関東', '栃木県': '関東', '群馬県': '関東', '埼玉県': '関東', '千葉県': '関東', '東京都': '関東', '神奈川県': '関東', '新潟県': '中部', '富山県': '中部', '石川県': '中部', '福井県': '中部', '山梨県': '中部', '長野県': '中部', '岐阜県': '中部', '静岡県': '中部', '愛知県': '中部', '三重県': '近畿', '滋賀県': '近畿', '京都府': '近畿', '大阪府': '近畿', '兵庫県': '近畿', '奈良県': '近畿', '和歌山県': '近畿', '鳥取県': '中国', '島根県': '中国', '岡山県': '中国', '広島県': '中国', '山口県': '中国', '徳島県': '四国', '香川県': '四国', '愛媛県': '四国', '高知県': '四国', '福岡県': '九州', '佐賀県': '九州', '長崎県': '九州', '熊本県': '九州', '大分県': '九州', '宮崎県': '九州', '鹿児島県': '九州', '沖縄県': '九州', } region_colors = { '北海道': '#1565C0', '東北': '#2E7D32', '関東': '#F57F17', '中部': '#6A1B9A', '近畿': '#C62828', '中国': '#00838F', '四国': '#E65100', '九州': '#37474F', } d22_sc = d22_sc.copy() d22_sc['region'] = d22_sc['Prefecture'].map(region_map).fillna('その他') plotted_regions = set() for _, row in d22_sc.iterrows(): reg = row['region'] col = region_colors.get(reg, '#888888') label = reg if reg not in plotted_regions else '_nolegend_' ax2.scatter(row['高齢化率'], row['医療機関密度_総合'], color=col, s=60, alpha=0.85, label=label, zorder=3) plotted_regions.add(reg) ax2.annotate(row['Prefecture'].replace('県', '').replace('都', '').replace('府', '').replace('道', ''), (row['高齢化率'], row['医療機関密度_総合']), textcoords='offset points', xytext=(5, 3), fontsize=7.5, color='#333') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。for _, row in df.iterrows() — DataFrameを1行ずつ取り出すループ。1点ずつ描画したいときに使用。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | # 回帰直線 x_sc = d22_sc['高齢化率'].values y_sc = d22_sc['医療機関密度_総合'].values slope, intercept, r, p, _ = stats.linregress(x_sc, y_sc) x_line = np.linspace(x_sc.min(), x_sc.max(), 100) ax2.plot(x_line, slope * x_line + intercept, 'k--', linewidth=1.5, alpha=0.6, label=f'回帰直線 (r={r:.3f}, p={p:.3f})') ax2.set_xlabel('高齢化率(65歳以上人口比率, %)', fontsize=11) ax2.set_ylabel('医療機関密度_総合(人口1万人当たり)', fontsize=11) ax2.set_title('Fig 2|高齢化率 × 医療機関密度(2022年・47都道府県)', fontsize=13, fontweight='bold', pad=14) ax2.legend(fontsize=9, loc='upper left', ncol=2) fig2.tight_layout() fig2_path = os.path.join(FIG_DIR, '2021_U4_fig2_scatter.png') fig2.savefig(fig2_path, dpi=150, bbox_inches='tight') plt.close(fig2) print(f"Fig2 保存: {fig2_path}") |
Fig2 保存: html/figures/2021_U4_fig2_scatter.png
stats.linregress(x, y) — 単回帰の傾き・切片・r値・p値・標準誤差を返します。使わない値は _ で受け取り。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。需要側(高齢化率・保健医療費)と供給側(消費支出)の3変数を説明変数とするOLS重回帰モデルを推定する。標準化係数(βを使用することで、単位の異なる変数の相対的な影響力を比較できる。
| 説明変数 | 標準化係数(β) | 95%信頼区間 | p値 | 有意性 |
|---|---|---|---|---|
| 高齢化率 | +0.404 | [+0.110, +0.698] | 0.010 | * |
| 消費支出(log) | −0.463 | [−0.826, −0.099] | 0.017 | * |
| 保健医療費(千円) | +0.518 | [+0.132, +0.903] | 0.012 | * |
N=47(2022年断面)。標準化係数はすべての変数をzスコア変換後に推定。
医療機関の立地は「需要」と「供給」の両面から決まる。需要側:高齢者・慢性疾患患者が多い地域では受診頻度が高く、医療機関の採算が取れる。供給側:医師は高賃金・利便性を求めて都市部に集中しやすいが、農村地域では公立病院への配置が医師配置を補完する。
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | d_ols = d22.dropna(subset=['医療機関密度_総合', '高齢化率', '消費支出_log', '保健医療費_千円']).copy() def standardize(s): return (s - s.mean()) / s.std() y_std = standardize(d_ols['医療機関密度_総合']) X_dict = { '高齢化率': standardize(d_ols['高齢化率']), '消費支出(log)': standardize(d_ols['消費支出_log']), '保健医療費(千円)': standardize(d_ols['保健医療費_千円']), } coef_results = {} for name, xvar in X_dict.items(): X_mat = np.column_stack([np.ones(len(xvar)), xvar.values]) beta, res, rank, sv = np.linalg.lstsq(X_mat, y_std.values, rcond=None) # 標準誤差 n_, k_ = X_mat.shape y_hat = X_mat @ beta sigma2 = np.sum((y_std.values - y_hat)**2) / (n_ - k_) cov_mat = sigma2 * np.linalg.inv(X_mat.T @ X_mat) se = np.sqrt(np.diag(cov_mat)) t_stat = beta[1] / se[1] p_val = 2 * stats.t.sf(abs(t_stat), df=n_ - k_) ci95 = 1.96 * se[1] coef_results[name] = {'coef': beta[1], 'ci': ci95, 'p': p_val} |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 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 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | # 複合OLS(全変数投入) X_all = np.column_stack([ np.ones(len(d_ols)), X_dict['高齢化率'].values, X_dict['消費支出(log)'].values, X_dict['保健医療費(千円)'].values, ]) beta_all, _, _, _ = np.linalg.lstsq(X_all, y_std.values, rcond=None) n_a, k_a = X_all.shape y_hat_a = X_all @ beta_all sigma2_a = np.sum((y_std.values - y_hat_a)**2) / (n_a - k_a) cov_all = sigma2_a * np.linalg.inv(X_all.T @ X_all) se_all = np.sqrt(np.diag(cov_all)) multi_coefs = { '高齢化率': (beta_all[1], 1.96 * se_all[1], 2 * stats.t.sf(abs(beta_all[1] / se_all[1]), df=n_a - k_a)), '消費支出(log)': (beta_all[2], 1.96 * se_all[2], 2 * stats.t.sf(abs(beta_all[2] / se_all[2]), df=n_a - k_a)), '保健医療費(千円)': (beta_all[3], 1.96 * se_all[3], 2 * stats.t.sf(abs(beta_all[3] / se_all[3]), df=n_a - k_a)), } print("\n--- OLS結果 (標準化係数, N=47都道府県, 2022年) ---") for vname, (c, ci, p) in multi_coefs.items(): sig = '***' if p < 0.001 else ('**' if p < 0.01 else ('*' if p < 0.05 else 'n.s.')) print(f" {vname:18s}: β={c:+.4f} 95%CI[{c-ci:+.4f}, {c+ci:+.4f}] p={p:.4f} {sig}") fig3, ax3 = plt.subplots(figsize=(8, 5)) var_labels = list(multi_coefs.keys()) coefs = [multi_coefs[v][0] for v in var_labels] cis = [multi_coefs[v][1] for v in var_labels] pvals = [multi_coefs[v][2] for v in var_labels] colors_ols = ['#1565C0' if c > 0 else '#C62828' for c in coefs] y_pos = np.arange(len(var_labels)) ax3.barh(y_pos, coefs, xerr=cis, color=colors_ols, alpha=0.80, height=0.5, error_kw={'elinewidth': 2, 'capsize': 5, 'ecolor': '#333'}) for i, (c, p) in enumerate(zip(coefs, pvals)): sig_str = '***' if p < 0.001 else ('**' if p < 0.01 else ('*' if p < 0.05 else 'n.s.')) ax3.text(c + (cis[i] + 0.02) * np.sign(c), i, sig_str, va='center', fontsize=11, fontweight='bold', color='#333' if sig_str != 'n.s.' else '#999') ax3.axvline(0, color='black', linewidth=1.0, linestyle='-') ax3.set_yticks(y_pos) ax3.set_yticklabels(var_labels, fontsize=11) ax3.set_xlabel('標準化回帰係数(β)± 95%信頼区間', fontsize=11) ax3.set_title('Fig 3|医療機関密度の決定要因\nOLS標準化係数(2022年断面, N=47)', fontsize=13, fontweight='bold', pad=14) ax3.text(0.99, 0.03, '***p<0.001 **p<0.01 *p<0.05 n.s.=有意でない', transform=ax3.transAxes, ha='right', va='bottom', fontsize=9, color='#555') fig3.tight_layout() fig3_path = os.path.join(FIG_DIR, '2021_U4_fig3_ols.png') fig3.savefig(fig3_path, dpi=150, bbox_inches='tight') plt.close(fig3) print(f"Fig3 保存: {fig3_path}") |
--- OLS結果 (標準化係数, N=47都道府県, 2022年) --- 高齢化率 : β=+0.4041 95%CI[+0.1099, +0.6982] p=0.0101 * 消費支出(log) : β=-0.4625 95%CI[-0.8258, -0.0993] p=0.0165 * 保健医療費(千円) : β=+0.5177 95%CI[+0.1323, +0.9031] p=0.0117 * Fig3 保存: html/figures/2021_U4_fig3_ols.png
fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。2012〜2023年の12年間にわたり、8地域ブロック別の医療機関密度_総合(平均)の推移を追う。医療機関数が増加しているのか、それとも全国的に減少しているのかを確認する。
時系列分析からは「地域格差が縮小されているか」を評価できる。格差が拡大傾向なら政策介入が必要、縮小傾向なら既存施策が奏功していることを示唆する。統計から格差の「方向性」を読み取ることが政策評価の第一歩。
249 250 251 252 253 254 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 | df_ts = df_all[df_all['year'].between(2012, 2023)].copy() df_ts['region'] = df_ts['Prefecture'].map(region_map).fillna('その他') df_ts = df_ts.dropna(subset=['医療機関密度_総合']) region_ts = ( df_ts.groupby(['year', 'region'])['医療機関密度_総合'] .mean() .reset_index() ) region_order = ['北海道', '東北', '関東', '中部', '近畿', '中国', '四国', '九州'] region_ls = ['-', '--', '-.', ':', '-', '--', '-.', ':'] fig4, ax4 = plt.subplots(figsize=(11, 6)) for reg, ls_ in zip(region_order, region_ls): sub = region_ts[region_ts['region'] == reg].sort_values('year') col = region_colors.get(reg, '#888') ax4.plot(sub['year'], sub['医療機関密度_総合'], marker='o', markersize=5, linewidth=2.2, linestyle=ls_, color=col, label=reg, alpha=0.9) ax4.set_xlabel('年度', fontsize=11) ax4.set_ylabel('医療機関密度_総合(人口1万人当たり)', fontsize=11) ax4.set_title('Fig 4|地域別 医療機関密度の時系列推移(2012〜2023年)\n8地域平均(一般病院+一般診療所)', fontsize=13, fontweight='bold', pad=14) ax4.set_xticks(range(2012, 2024)) ax4.xaxis.set_tick_params(rotation=45) ax4.legend(loc='upper right', fontsize=10, ncol=2) ax4.yaxis.set_major_formatter(mticker.FormatStrFormatter('%.1f')) fig4.tight_layout() fig4_path = os.path.join(FIG_DIR, '2021_U4_fig4_timeseries.png') fig4.savefig(fig4_path, dpi=150, bbox_inches='tight') plt.close(fig4) print(f"Fig4 保存: {fig4_path}") print("\n=== 全図の出力が完了しました ===") print(f"出力先: {FIG_DIR}") |
Fig4 保存: html/figures/2021_U4_fig4_timeseries.png === 全図の出力が完了しました === 出力先: html/figures
df.groupby('列').apply(関数) — グループごとに関数を適用。時系列や地域別の集計でよく使います。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。SSDSE-B(47都道府県、2012〜2023年)を用いた分析から、以下のことが明らかになった:
ローレンツ曲線は、人口(X軸)と医療資源(Y軸)の累積分布を対角線(完全平等線)と比較することで格差を可視化する。ジニ係数は完全平等(0)から完全不平等(1)の間の値を取り、格差の大きさを一つの数値で表す。
| データ | 出典・説明 |
|---|---|
| SSDSE-B-2026.csv | 統計数理研究所 SSDSE(社会・人口統計体系)— 都道府県別パネルデータ(2012〜2023年) |
| 一般病院数(I510120) | 厚生労働省 医療施設調査(SSDSE-B 収録) |
| 一般診療所数(I5102) | 厚生労働省 医療施設調査(SSDSE-B 収録) |
| 歯科診療所数(I5103) | 厚生労働省 医療施設調査(SSDSE-B 収録) |
| 消費支出・保健医療費(L3221, L322106) | 総務省 家計調査(SSDSE-B 収録) |
本教育用コードはSSDSE-B-2026.csv の実データのみを使用。合成データ(np.random.seed等)は一切使用していない。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。