このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
観光業は「地域経済の起爆剤」と言われる。旅行者が宿泊施設・飲食店・土産店などにお金を使うことで、地域の消費が活性化し、雇用が生まれ、所得が増える。これを観光の乗数効果(Tourism Multiplier Effect)という。本研究は、都道府県レベルの延べ宿泊者数が消費支出に与える影響を統計的に分析した。
まず「観光業と地域経済延べ宿泊者数が消費支出に与える影響」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。
2020〜2021年はCOVID-19により宿泊者数が急減した。この「観光業の外生的ショック」は、観光と地域経済の因果関係を検証する自然実験(Natural Experiment)の機会ともなった。
相関分析 OLS回帰 時系列分析 パネルデータ インバウンド需要
統計数理研究所が公開するSSDSE-B(社会・人口統計体系、都道府県版)を使用。2012〜2022年の47都道府県、合計517件のパネルデータ(都道府県×年度)。
| 指標名 | 定義式 | SSDSE-B列名 | 役割 |
|---|---|---|---|
| 消費支出_万円 | 消費支出(二人以上の世帯)÷ 10000 | L3221 | 目的変数(万円/月) |
| 宿泊密度 | 延べ宿泊者数 ÷ 総人口 | G7101, A1101 | 観光強度(主要説明変数) |
| 外国人比率(%) | 外国人延べ宿泊者数 ÷ 延べ宿泊者数 × 100 | G7102, G7101 | インバウンド需要の強さ |
| 旅館密度 | 旅館営業施設数 ÷ 総人口 × 10000 | C3801, A1101 | 観光インフラの充実度 |
| 高齢化率(%) | 65歳以上人口 ÷ 総人口 × 100 | A1303, A1101 | 人口構造のコントロール変数 |
異なるスケールの地域を比較するとき、絶対値ではなく「人口1人あたり」や「面積あたり」の指標を使うことが重要。これをNormalization(正規化・標準化)という。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | df_raw = pd.read_csv(DATA_B, encoding='shift-jis', header=0) # 行0がラベル行、行1以降が実データ df_all = df_raw.iloc[1:].copy() df_all.columns = df_raw.columns # 数値列に変換 NUM_COLS = ['A1101', 'A1303', 'C3801', 'G7101', 'G7102', 'L3221'] for c in NUM_COLS: df_all[c] = pd.to_numeric(df_all[c], errors='coerce') df_all['年度'] = df_all['SSDSE-B-2026'].astype(int) df_all['都道府県'] = df_all['Prefecture'] print("=" * 65) print("■ SSDSE-B-2026 読み込み完了") print(f" 年度範囲: {df_all['年度'].min()}〜{df_all['年度'].max()}") print(f" 都道府県数(各年): {df_all.groupby('年度')['都道府県'].count().iloc[0]}件") print("=" * 65) |
================================================================= ■ SSDSE-B-2026 読み込み完了 年度範囲: 2012〜2023 都道府県数(各年): 47件 =================================================================
pd.read_csv(...) でCSVを読み込みます。encoding='cp932' は日本語Windows由来の文字コード、header=1 は「2行目を列名として使う」。.astype(int) — 列を整数に変換(年度などを数値比較するため)。df.groupby('列').apply(関数) — グループごとに関数を適用。時系列や地域別の集計でよく使います。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | df_all['宿泊密度'] = df_all['G7101'] / df_all['A1101'].clip(1) df_all['外国人比率'] = df_all['G7102'] / df_all['G7101'].clip(1) * 100 df_all['消費支出_万円'] = df_all['L3221'] / 10000 df_all['旅館密度'] = df_all['C3801'] / df_all['A1101'].clip(1) * 10000 df_all['高齢化率'] = df_all['A1303'] / df_all['A1101'].clip(1) * 100 # 2022年データ抽出 df_2022 = df_all[df_all['年度'] == 2022].copy().reset_index(drop=True) # 2019年データ抽出(コロナ前比較用) df_2019 = df_all[df_all['年度'] == 2019].copy().reset_index(drop=True) print(f"\n■ 2022年データ: {len(df_2022)}都道府県") print(f" 宿泊密度(平均): {df_2022['宿泊密度'].mean():.4f}") print(f" 外国人比率(平均): {df_2022['外国人比率'].mean():.2f}%") print(f" 消費支出(平均): {df_2022['消費支出_万円'].mean():.2f}万円/月") |
■ 2022年データ: 47都道府県 宿泊密度(平均): 3.2647 外国人比率(平均): 1.70% 消費支出(平均): 28.96万円/月
.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。2012年から2019年にかけて、日本全体の延べ宿泊者数は増加傾向にあった。訪日外国人(インバウンド)の急増が主な要因である。しかし2020年のCOVID-19感染拡大により、宿泊者数は約半減するという歴史的な急落を経験した。
「自然実験(Natural Experiment)」とは、研究者が操作しない外生的ショックを、あたかも実験の「処置」として使う分析手法である。COVID-19による観光業の急落は典型的な自然実験と見なせる。
「差の差推定(Difference-in-Differences, DiD)」は、ショックの影響を「ショック前後の変化量の差」で測る方法。観光依存度が高い都道府県(処置群)と低い都道府県(対照群)に分けて比較する。
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 77 78 79 80 81 82 | print("\n" + "=" * 65) print("■ 図1: 時系列推移(地域別)") print("=" * 65) # 地方区分 REGION_MAP = { '北海道': '北海道・東北', '青森県': '北海道・東北', '岩手県': '北海道・東北', '宮城県': '北海道・東北', '秋田県': '北海道・東北', '山形県': '北海道・東北', '福島県': '北海道・東北', '茨城県': '関東', '栃木県': '関東', '群馬県': '関東', '埼玉県': '関東', '千葉県': '関東', '東京都': '関東', '神奈川県': '関東', '新潟県': '中部', '富山県': '中部', '石川県': '中部', '福井県': '中部', '山梨県': '中部', '長野県': '中部', '岐阜県': '中部', '静岡県': '中部', '愛知県': '中部', '三重県': '近畿', '滋賀県': '近畿', '京都府': '近畿', '大阪府': '近畿', '兵庫県': '近畿', '奈良県': '近畿', '和歌山県': '近畿', '鳥取県': '中国・四国', '島根県': '中国・四国', '岡山県': '中国・四国', '広島県': '中国・四国', '山口県': '中国・四国', '徳島県': '中国・四国', '香川県': '中国・四国', '愛媛県': '中国・四国', '高知県': '中国・四国', '福岡県': '九州・沖縄', '佐賀県': '九州・沖縄', '長崎県': '九州・沖縄', '熊本県': '九州・沖縄', '大分県': '九州・沖縄', '宮崎県': '九州・沖縄', '鹿児島県': '九州・沖縄', '沖縄県': '九州・沖縄', } REGION_ORDER = ['北海道・東北', '関東', '中部', '近畿', '中国・四国', '九州・沖縄'] REGION_COLORS = { '北海道・東北': '#1565C0', '関東': '#E65100', '中部': '#2E7D32', '近畿': '#6A1B9A', '中国・四国': '#795548', '九州・沖縄': '#00695C', } df_all['地方'] = df_all['都道府県'].map(REGION_MAP) df_region_ts = ( df_all.groupby(['年度', '地方'])['G7101'] .sum() .reset_index() ) df_region_ts['宿泊者数_億人'] = df_region_ts['G7101'] / 1e8 fig1, ax1 = plt.subplots(figsize=(11, 6)) for region in REGION_ORDER: sub = df_region_ts[df_region_ts['地方'] == region].sort_values('年度') if len(sub) == 0: continue ax1.plot(sub['年度'], sub['宿泊者数_億人'], marker='o', linewidth=2, markersize=5, color=REGION_COLORS[region], label=region) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df.groupby('列').apply(関数) — グループごとに関数を適用。時系列や地域別の集計でよく使います。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | # COVID期を強調 ax1.axvspan(2019.5, 2021.5, alpha=0.12, color='#C62828', zorder=0) ax1.axvline(2019.5, color='#C62828', linestyle='--', linewidth=1.2, alpha=0.7) ax1.axvline(2021.5, color='#C62828', linestyle='--', linewidth=1.2, alpha=0.7) ax1.text(2020.4, ax1.get_ylim()[1] * 0.97, 'COVID-19\n急減期', ha='center', va='top', fontsize=9.5, color='#C62828', fontweight='bold') ax1.set_xlabel('年度', fontsize=12) ax1.set_ylabel('延べ宿泊者数(億人泊)', fontsize=12) ax1.set_title('延べ宿泊者数の時系列推移(地方別)\n〜COVID-19による急減と回復〜', fontsize=13, fontweight='bold') ax1.set_xticks(sorted(df_region_ts['年度'].unique())) ax1.xaxis.set_tick_params(rotation=45) ax1.legend(loc='upper left', fontsize=9.5, framealpha=0.85) ax1.grid(True, alpha=0.3) plt.tight_layout() fig1.savefig(os.path.join(FIG_DIR, '2022_H5_5_fig1_timeseries.png'), bbox_inches='tight', dpi=150) plt.close(fig1) print("図1保存: 2022_H5_5_fig1_timeseries.png") |
================================================================= ■ 図1: 時系列推移(地域別) ================================================================= 図1保存: 2022_H5_5_fig1_timeseries.png
ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。2022年データを用いて、都道府県別の宿泊密度(観光強度)と消費支出の関係を散布図で可視化する。点の色は外国人宿泊比率を表し、インバウンドの影響も同時に把握できる。
104 105 106 107 108 109 110 | print("\n■ 図2: 散布図(宿泊密度 vs 消費支出)") fig2, ax2 = plt.subplots(figsize=(11, 7)) x2 = df_2022['宿泊密度'].values y2 = df_2022['消費支出_万円'].values pref2 = df_2022['都道府県'].values |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。111 112 113 114 115 116 | # 散布図 sc2 = ax2.scatter(x2, y2, c=df_2022['外国人比率'].values, cmap='YlOrRd', s=70, alpha=0.85, edgecolors='#333', linewidth=0.5, zorder=3) cbar2 = fig2.colorbar(sc2, ax=ax2, label='外国人比率(%)', shrink=0.8) cbar2.ax.tick_params(labelsize=9) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。117 118 119 120 121 122 | # 回帰直線 valid_mask = np.isfinite(x2) & np.isfinite(y2) z2 = np.polyfit(x2[valid_mask], y2[valid_mask], 1) xs2 = np.linspace(x2[valid_mask].min(), x2[valid_mask].max(), 100) ax2.plot(xs2, np.poly1d(z2)(xs2), 'b--', linewidth=1.8, alpha=0.7, label=f'回帰直線 (r={r_corr:.3f}, p={p_corr:.4f})') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。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 | # 都道府県ラベル(上位・下位・注目都市) LABEL_PREFS = { '東京都', '北海道', '沖縄県', '京都府', '大阪府', '長野県', '山梨県', '石川県', '秋田県', '鳥取県', '神奈川県', '愛知県', '福岡県', } for i, (xi, yi, pref) in enumerate(zip(x2, y2, pref2)): if pref in LABEL_PREFS: short = pref.replace('県', '').replace('都', '').replace('道', '').replace('府', '') ax2.annotate(short, (xi, yi), xytext=(4, 3), textcoords='offset points', fontsize=7.5, color='#1A237E', fontweight='bold') ax2.set_xlabel('宿泊密度(延べ宿泊者数/総人口)', fontsize=12) ax2.set_ylabel('消費支出(万円/月, 二人以上の世帯)', fontsize=12) ax2.set_title('宿泊密度と消費支出の関係(2022年, 都道府県別)\n〜色:外国人延べ宿泊比率〜', fontsize=13, fontweight='bold') ax2.legend(fontsize=9.5) ax2.grid(True, alpha=0.3) plt.tight_layout() fig2.savefig(os.path.join(FIG_DIR, '2022_H5_5_fig2_scatter.png'), bbox_inches='tight', dpi=150) plt.close(fig2) print("図2保存: 2022_H5_5_fig2_scatter.png") |
■ 図2: 散布図(宿泊密度 vs 消費支出) 図2保存: 2022_H5_5_fig2_scatter.png
np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。宿泊密度・外国人比率・旅館密度・高齢化率を説明変数とし、消費支出を目的変数とするOLS(最小二乗法)重回帰分析を実施する。係数は解釈しやすいよう標準化(平均0・標準偏差1)してから推定する。
| 変数 | 係数(標準化) | p値 | 解釈 |
|---|---|---|---|
| 宿泊密度 | −0.577 | 0.189 | 非有意(交絡の影響) |
| 外国人比率 | +0.007 | 0.985 | 非有意 |
| 旅館密度 | −0.118 | 0.779 | 非有意 |
| 高齢化率 | −0.767 | 0.019* | 有意に負(高齢化が消費を抑制) |
観光客が1万円使うと、受け取った宿泊業者・飲食店はその一部を仕入れや人件費に使い、さらにその受け取り手が消費を行う……この連鎖を「乗数効果(Multiplier Effect)」という。
統計的に乗数効果を測るには、観光支出を説明変数、地域のGDPや消費支出を目的変数としたOLS回帰が基本。ただし観光需要自体が地域の豊かさに影響されるため(同時性バイアス)、操作変数法やパネル分析での対処が必要になる。
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | print("\n■ 図3: OLS回帰係数プロット") coefs3 = np.asarray(ols_model.params[1:]) ses3 = np.asarray(ols_model.bse[1:]) pvals3 = np.asarray(ols_model.pvalues[1:]) ci_lo3 = coefs3 - 1.96 * ses3 ci_hi3 = coefs3 + 1.96 * ses3 COEF_COLORS = [] for p in pvals3: if p < 0.01: COEF_COLORS.append('#C62828') elif p < 0.05: COEF_COLORS.append('#FF8F00') elif p < 0.10: COEF_COLORS.append('#FDD835') else: COEF_COLORS.append('#9E9E9E') fig3, ax3 = plt.subplots(figsize=(9, 5)) y_pos3 = np.arange(len(REG_LABELS)) ax3.barh(y_pos3, coefs3, color=COEF_COLORS, alpha=0.80, edgecolor='white', height=0.55) ax3.errorbar(coefs3, y_pos3, xerr=1.96 * ses3, fmt='none', color='#222', capsize=5, linewidth=1.5) ax3.axvline(0, color='gray', linestyle='--', linewidth=1.0) ax3.set_yticks(y_pos3) ax3.set_yticklabels(REG_LABELS, fontsize=11) ax3.set_xlabel('標準化回帰係数(±1.96SE)', fontsize=11) ax3.set_title( f'消費支出の決定要因 — OLS回帰係数(2022年, N={len(df_reg)}都道府県)\n' f'R²={ols_model.rsquared:.3f}(adj. R²={ols_model.rsquared_adj:.3f})', fontsize=12, fontweight='bold' ) ax3.invert_yaxis() ax3.grid(axis='x', alpha=0.3) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | # p値ラベル for i, (c, p) in enumerate(zip(coefs3, pvals3)): sig = '***' if p < 0.001 else '**' if p < 0.01 else '*' if p < 0.05 else 'n.s.' offset = 0.008 if c >= 0 else -0.008 ha = 'left' if c >= 0 else 'right' ax3.text(c + offset, i, f' {c:.3f} {sig}', va='center', ha=ha, fontsize=8.5) from matplotlib.patches import Patch ax3.legend(handles=[ Patch(color='#C62828', alpha=0.8, label='p<0.01'), Patch(color='#FF8F00', alpha=0.8, label='p<0.05'), Patch(color='#FDD835', alpha=0.8, label='p<0.10'), Patch(color='#9E9E9E', alpha=0.8, label='n.s.'), ], fontsize=9, loc='lower right') plt.tight_layout() fig3.savefig(os.path.join(FIG_DIR, '2022_H5_5_fig3_coef.png'), bbox_inches='tight', dpi=150) plt.close(fig3) print("図3保存: 2022_H5_5_fig3_coef.png") |
■ 図3: OLS回帰係数プロット 図3保存: 2022_H5_5_fig3_coef.png
import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。COVID-19は国内旅行と外国人旅行に異なる影響を与えた。入国制限により外国人宿泊者はほぼゼロになり(2021年)、その後の回復速度も地域によって大きく異なる。2019年(コロナ前)と2022年(回復期)を比較することで、各都道府県のインバウンド依存度の変化が明確になる。
「インバウンド需要の強さ」を表す指標として、外国人延べ宿泊者数を全延べ宿泊者数で割った「外国人比率」を使う。この指標により都道府県間の比較が可能になる。
外国人旅行者は国内旅行者より一般的に消費単価が高い傾向があるため、外国人比率が高い地域では宿泊業・飲食業の売上への波及効果も大きい可能性がある。
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | import numpy as np import pandas as pd import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import statsmodels.api as sm from scipy import stats 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} のように書式も指定できます。225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | print("\n" + "=" * 65) print("■ OLS回帰分析(2022年)") print("=" * 65) REG_VARS = ['宿泊密度', '外国人比率', '旅館密度', '高齢化率'] REG_LABELS = ['宿泊密度', '外国人比率(%)', '旅館密度(万人対)', '高齢化率(%)'] df_reg = df_2022[['消費支出_万円'] + REG_VARS].dropna() y_ols = df_reg['消費支出_万円'].values X_ols = df_reg[REG_VARS].values # 標準化(係数の比較のため) X_std = (X_ols - X_ols.mean(axis=0)) / X_ols.std(axis=0) X_with_const = sm.add_constant(X_std) ols_model = sm.OLS(y_ols, X_with_const).fit() print(ols_model.summary2()) print(f"\n R² = {ols_model.rsquared:.4f}") print(f" 自由度修正済R² = {ols_model.rsquared_adj:.4f}") # 相関分析 print("\n■ 相関分析(宿泊密度 vs 消費支出_万円)") r_corr, p_corr = stats.pearsonr(df_2022['宿泊密度'].dropna(), df_2022['消費支出_万円'].dropna()) print(f" r = {r_corr:.4f}, p = {p_corr:.4f}") |
=================================================================
■ OLS回帰分析(2022年)
=================================================================
Results: Ordinary least squares
=================================================================
Model: OLS Adj. R-squared: 0.180
Dependent Variable: y AIC: 190.0013
Date: 2026-05-18 11:24 BIC: 199.2520
No. Observations: 47 Log-Likelihood: -90.001
Df Model: 4 F-statistic: 3.530
Df Residuals: 42 Prob (F-statistic): 0.0143
R-squared: 0.252 Scale: 3.0175
-------------------------------------------------------------------
Coef. Std.Err. t P>|t| [0.025 0.975]
-------------------------------------------------------------------
const 28.9630 0.2534 114.3069 0.0000 28.4517 29.4744
x1 -0.5766 0.4313 -1.3367 0.1885 -1.4470 0.2939
x2 0.0066 0.3545 0.0187 0.9851 -0.7089 0.7221
x3 -0.1183 0.4197 -0.2819 0.7794 -0.9653 0.7287
x4 -0.7667 0.3146 -2.4367 0.0191 -1.4017 -0.1317
-----------------------------------------------------------------
Omnibus: 1.876 Durbin-Watson: 1.745
Prob(Omnibus): 0.392 Jarque-Bera (JB): 1.600
Skew: -0.446 Prob(JB): 0.449
Kurtosis: 2.854 Condition No.: 3
=================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the
errors is correctly specified.
R² = 0.2516
自由度修正済R² = 0.1803
■ 相関分析(宿泊密度 vs 消費支出_万円)
r = -0.2812, p = 0.0556stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。sm.add_constant(X) — 切片項(定数1の列)を先頭に追加。statsmodelsで必須。sm.OLS(y, X).fit() — 最小二乗法でモデルを推定。model.params, model.pvalues, model.conf_int() で結果取得。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。250 251 252 253 254 255 256 257 | print("\n■ 図4: 外国人比率ランキング(2019 vs 2022)") # 2019年・2022年の外国人比率 df_inbound = pd.merge( df_2019[['都道府県', '外国人比率']].rename(columns={'外国人比率': '外国人比率_2019'}), df_2022[['都道府県', '外国人比率']].rename(columns={'外国人比率': '外国人比率_2022'}), on='都道府県', how='inner' ).dropna() |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | # 2019年基準でソート(上位20都道府県) df_inbound_sorted = df_inbound.sort_values('外国人比率_2019', ascending=True).tail(20) prefs4 = df_inbound_sorted['都道府県'].str.replace('県', '').str.replace('都', '') \ .str.replace('道', '').str.replace('府', '').values v2019 = df_inbound_sorted['外国人比率_2019'].values v2022 = df_inbound_sorted['外国人比率_2022'].values fig4, ax4 = plt.subplots(figsize=(10, 8)) y_pos4 = np.arange(len(prefs4)) bar_h = 0.38 bars_2019 = ax4.barh(y_pos4 + bar_h / 2, v2019, height=bar_h, color='#1565C0', alpha=0.80, label='2019年(コロナ前)', edgecolor='white') bars_2022 = ax4.barh(y_pos4 - bar_h / 2, v2022, height=bar_h, color='#E65100', alpha=0.80, label='2022年(コロナ後回復期)', edgecolor='white') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | # 数値ラベル for bar, val in zip(bars_2019, v2019): ax4.text(val + 0.2, bar.get_y() + bar.get_height() / 2, f'{val:.1f}%', va='center', ha='left', fontsize=7.5) for bar, val in zip(bars_2022, v2022): ax4.text(val + 0.2, bar.get_y() + bar.get_height() / 2, f'{val:.1f}%', va='center', ha='left', fontsize=7.5) ax4.set_yticks(y_pos4) ax4.set_yticklabels(prefs4, fontsize=9.5) ax4.set_xlabel('外国人延べ宿泊比率(%)', fontsize=11) ax4.set_title('外国人宿泊比率ランキング — 2019年 vs 2022年\n〜上位20都道府県、2019年基準〜', fontsize=13, fontweight='bold') ax4.legend(fontsize=10) ax4.grid(axis='x', alpha=0.3) plt.tight_layout() fig4.savefig(os.path.join(FIG_DIR, '2022_H5_5_fig4_inbound.png'), bbox_inches='tight', dpi=150) plt.close(fig4) print("図4保存: 2022_H5_5_fig4_inbound.png") |
■ 図4: 外国人比率ランキング(2019 vs 2022) 図4保存: 2022_H5_5_fig4_inbound.png
{値:.2f}(小数2桁)、{値:,}(3桁区切り)、{値:>10}(右寄せ10桁)など、覚えると出力が一気に整います。295 296 297 298 299 300 301 | print("\n" + "=" * 65) print("■ 全図生成完了(4枚)") print(f" fig1_timeseries.png : 延べ宿泊者数の時系列推移(地方別)") print(f" fig2_scatter.png : 宿泊密度 vs 消費支出 散布図(2022年)") print(f" fig3_coef.png : OLS回帰係数プロット") print(f" fig4_inbound.png : 外国人比率ランキング(2019 vs 2022)") print("=" * 65) |
================================================================= ■ 全図生成完了(4枚) fig1_timeseries.png : 延べ宿泊者数の時系列推移(地方別) fig2_scatter.png : 宿泊密度 vs 消費支出 散布図(2022年) fig3_coef.png : OLS回帰係数プロット fig4_inbound.png : 外国人比率ランキング(2019 vs 2022) =================================================================
np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。| データ | 変数名(SSDSE-B) | 出典 |
|---|---|---|
| 延べ宿泊者数 | G7101 | 観光庁 宿泊旅行統計調査(SSDSE-B経由) |
| 外国人延べ宿泊者数 | G7102 | 観光庁 宿泊旅行統計調査(SSDSE-B経由) |
| 消費支出(二人以上の世帯) | L3221 | 総務省 家計調査(SSDSE-B経由) |
| 旅館営業施設数(ホテルを含む) | C3801 | 厚生労働省 衛生行政報告例(SSDSE-B経由) |
| 総人口・65歳以上人口 | A1101, A1303 | 総務省 住民基本台帳(SSDSE-B経由) |
本教育用コードはSSDSE-B-2026.csv(実公的データ)のみを使用。合成データ(np.random.seed等)は一切使用していない。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。