このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
日本の地域経済は都道府県ごとに大きく異なる産業構造を持ち、その差異が経済成長格差の根本要因と考えられる。本研究は産業集積の測定に特化係数(Location Quotient; LQ)を用い、各地域が全国平均に対してどの産業で特化しているかを定量化する。さらに主成分分析(PCA)による次元削減とWard法クラスタリングを組み合わせ、類似した産業構造を持つ地域グループを抽出して経済成長との関係を分析する。
まず「地域産業構造と経済成長特化係数・主成分分析による産業集積の分析」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。
特化係数(LQ) レーダーチャート 主成分分析(PCA) Ward法クラスタリング
SSDSE-B(都道府県・時系列データ)の2022年データ(47都道府県)を使用。SSDSE-Bには直接的な産業別就業者数は含まれないため、産業集積の強さを表す代理変数(Proxy Variable)を各種統計から構築する。
| 指標名 | 計算式 | 代理する産業 | 理由 |
|---|---|---|---|
| 観光特化 | 旅館施設数 ÷ 総人口 × 10,000 | 観光・宿泊業 | 観光地ほど旅館・ホテルの施設密度が高い |
| 農業特化代理 | 1000 ÷ 1人1日ごみ排出量 | 農業・第一次産業 | 農村地域は都市化が低く、1人当たりごみ排出量が少ない傾向 |
| 教育特化 | 大学学生数 ÷ 総人口 × 1,000 | 高等教育・知識産業 | 大学都市ほど学生密度(高等教育産業)が高い |
| 医療特化 | (病院数 + 診療所数) ÷ 総人口 × 10,000 | 医療・福祉産業 | 医療機関密度が医療産業集積を反映 |
| 建設特化代理 | 着工新設住宅戸数 ÷ 総人口 × 10,000 | 建設・不動産業 | 住宅着工数が建設需要・活動の代理 |
| 消費支出_log | log(消費支出(二人以上世帯)) | 経済成長代理 | 家計消費水準は地域経済活力の代理指標 |
| 指標 | 最小 | 第1四分位 | 中央値 | 第3四分位 | 最大 |
|---|---|---|---|---|---|
| 観光特化 | 0.17 | 0.57 | 0.90 | 1.21 | 3.64 |
| 農業特化代理 | 0.88 | 0.95 | 0.99 | 1.04 | 1.17 |
| 教育特化 | 0.50 | 0.64 | 0.83 | 1.21 | 3.57 |
| 医療特化 | 0.71 | 0.90 | 1.02 | 1.10 | 1.33 |
| 建設特化代理 | 0.66 | 0.88 | 0.96 | 1.10 | 1.61 |
| 消費支出_log | 0.987 | 0.997 | 1.000 | 1.004 | 1.009 |
※ 全国平均=1.0 に正規化。観光特化・教育特化は上位都道府県(北海道・京都府・東京都等)で顕著な集積が確認される。
1 2 3 4 5 6 7 8 9 10 11 | plt.rcParams['font.family'] = 'Hiragino Sans' plt.rcParams['axes.unicode_minus'] = False plt.rcParams['figure.dpi'] = 150 PREFIX = '2021_U3' def save_fig(label): path = os.path.join(FIG_DIR, f'{PREFIX}_{label}.png') plt.savefig(path, bbox_inches='tight', dpi=150) plt.close() print(f' → {path} 保存完了') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。plt.rcParams['font.family'] — グラフの日本語表示用フォント指定(Macは Hiragino Sans、Windowsなら Yu Gothic 等)。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | print('=== データ読み込み ===') df_raw = pd.read_csv(DATA_B, encoding='cp932', header=1) # 都道府県行のみ抽出(地域コードが R+5桁、かつ全国コードR00000を除外) mask = (df_raw['地域コード'].str.match(r'^R\d{5}$', na=False) & (df_raw['地域コード'] != 'R00000')) df_all = df_raw[mask].copy() # 2022年データ(消費支出が揃っている最新年) df = df_all[df_all['年度'] == 2022].copy().reset_index(drop=True) print(f'2022年データ: {len(df)}都道府県') # 数値変換 num_cols = ['総人口', '旅館営業施設数(ホテルを含む)', '大学学生数', '一般病院数', '一般診療所数', '着工新設住宅戸数', '1人1日当たりの排出量', '消費支出(二人以上の世帯)'] for c in num_cols: df[c] = pd.to_numeric(df[c], errors='coerce') # 欠損値確認 print('欠損値確認:') for c in num_cols: n_na = df[c].isna().sum() if n_na > 0: print(f' {c}: {n_na}件') |
=== データ読み込み === 2022年データ: 47都道府県 欠損値確認:
pd.read_csv(...) でCSVを読み込みます。encoding='cp932' は日本語Windows由来の文字コード、header=1 は「2行目を列名として使う」。df['地域コード'].str.match(r'^R\d{5}', ...) — 正規表現で「R+数字5桁」の行(47都道府県)だけTrueにし、真偽値で行をフィルタ。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。37 38 39 40 41 42 | print('\n=== 特化係数代理指標の計算 ===') pop = df['総人口'] # 観光特化: 旅館施設数 / 総人口 × 10000 df['観光特化'] = df['旅館営業施設数(ホテルを含む)'] / pop * 10000 |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。43 44 45 46 47 48 49 50 | # 農業特化代理: ごみ排出量の逆数(農村部はごみが少ない) df['農業特化代理'] = 1000 / df['1人1日当たりの排出量'] # 教育特化: 大学学生数 / 総人口 × 1000 df['教育特化'] = df['大学学生数'] / pop * 1000 # 医療特化: (病院数+診療所数) / 総人口 × 10000 df['医療特化'] = (df['一般病院数'] + df['一般診療所数']) / pop * 10000 |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。51 52 53 54 55 56 57 58 | # 建設特化代理: 新設住宅戸数 / 総人口 × 10000 df['建設特化代理'] = df['着工新設住宅戸数'] / pop * 10000 # 消費支出(log変換) df['消費支出_log'] = np.log(df['消費支出(二人以上の世帯)']) # 地域ブロック df['地域'] = df['都道府県'].map(REGION_MAP) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。59 60 61 62 63 64 65 | # 変数リスト VARS = ['観光特化', '農業特化代理', '教育特化', '医療特化', '建設特化代理', '消費支出_log'] VAR_LABELS = ['観光\n特化', '農業\n特化代理', '教育\n特化', '医療\n特化', '建設\n特化代理', '消費支出\n(log)'] # 欠損除去 df_clean = df[['都道府県', '地域'] + VARS + ['消費支出(二人以上の世帯)']].dropna().reset_index(drop=True) print(f'分析対象: {len(df_clean)}都道府県') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。66 67 68 | # 統計サマリー print('\n--- 代理指標サマリー ---') print(df_clean[VARS].describe().round(4).to_string()) |
=== 特化係数代理指標の計算 ===
分析対象: 47都道府県
--- 代理指標サマリー ---
観光特化 農業特化代理 教育特化 医療特化 建設特化代理 消費支出_log
count 47.0000 47.0000 47.0000 47.0000 47.0000 47.0000
mean 5.6553 1.1087 15.9686 9.1707 59.8700 12.5742
std 3.7709 0.0769 9.2636 1.3070 12.2704 0.0670
min 0.9418 0.9794 7.9506 6.5299 39.7443 12.4092
25% 3.1993 1.0510 10.1692 8.2601 52.8311 12.5312
50% 5.1036 1.0977 13.2351 9.3118 57.5526 12.5700
75% 6.8670 1.1581 19.3592 10.0431 65.7952 12.6190
max 20.5926 1.2987 56.9529 12.2370 96.4397 12.6909.describe() — 件数・平均・標準偏差・四分位・最大/最小を一括計算。データの素性チェックに必須。np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。69 70 71 72 73 74 75 76 77 78 | lq_df = df_clean[VARS].copy() for v in VARS: nat_mean = lq_df[v].mean() lq_df[v] = lq_df[v] / nat_mean # LQ: 地域値 / 全国平均 lq_df['地域'] = df_clean['地域'].values lq_df['都道府県'] = df_clean['都道府県'].values print('\n--- LQ値サマリー(全国平均=1.0)---') print(lq_df[VARS].describe().round(3).to_string()) |
--- LQ値サマリー(全国平均=1.0)---
観光特化 農業特化代理 教育特化 医療特化 建設特化代理 消費支出_log
count 47.000 47.000 47.000 47.000 47.000 47.000
mean 1.000 1.000 1.000 1.000 1.000 1.000
std 0.667 0.069 0.580 0.143 0.205 0.005
min 0.167 0.883 0.498 0.712 0.664 0.987
25% 0.566 0.948 0.637 0.901 0.882 0.997
50% 0.902 0.990 0.829 1.015 0.961 1.000
75% 1.214 1.044 1.212 1.095 1.099 1.004
max 3.641 1.171 3.567 1.334 1.611 1.009.describe() — 件数・平均・標準偏差・四分位・最大/最小を一括計算。データの素性チェックに必須。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。6産業特化指標のLQ値を地域ブロック(北海道・東北・関東・中部・近畿・中国四国・九州沖縄)ごとに平均し、レーダーチャートで可視化する。各地域のプロファイルを比較することで、産業構造の地域差を直感的に把握できる。
LQは地域の産業集積を全国平均との比率で測定する指標。LQ>1.0なら全国平均以上の特化、LQ<1.0なら平均以下。経済地理学・地域科学で広く使われる。
レーダーチャート(スパイダープロット)はmatplotlibのpolar=True座標系で作成する。N変数の場合、等間隔に0〜2πのN点の角度を設定し、最後に最初の点を追加してポリゴンを閉じる。
80 81 82 83 84 85 86 87 88 89 90 91 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 | print('\n=== Fig1: レーダーチャート ===') region_lq = lq_df.groupby('地域')[VARS].mean() N_vars = len(VARS) angles = np.linspace(0, 2 * np.pi, N_vars, endpoint=False).tolist() angles += angles[:1] # close the polygon fig, axes = plt.subplots(2, 3, figsize=(14, 9), subplot_kw=dict(polar=True)) fig.suptitle('地域ブロック別 産業特化指標(LQ代理)レーダーチャート\n(2022年, 全国平均=1.0)', fontsize=14, fontweight='bold', y=1.01) axes_flat = axes.flatten() for i, region in enumerate(REGION_ORDER[:6]): ax = axes_flat[i] if region not in region_lq.index: ax.set_visible(False) continue vals = region_lq.loc[region, VARS].tolist() vals += vals[:1] color = REGION_COLORS[region] ax.plot(angles, vals, color=color, linewidth=2.0) ax.fill(angles, vals, color=color, alpha=0.25) # 参照線(LQ=1.0) ax.plot(angles, [1.0] * len(angles), color='gray', linewidth=0.8, linestyle='--', alpha=0.6) ax.set_xticks(angles[:-1]) ax.set_xticklabels(VAR_LABELS, fontsize=8) ax.set_ylim(0, None) ax.set_title(region, fontsize=11, fontweight='bold', color=color, pad=12) ax.tick_params(axis='y', labelsize=7) plt.tight_layout() save_fig('fig1_radar') |
=== Fig1: レーダーチャート === → html/figures/2021_U3_fig1_radar.png 保存完了
df.groupby('列').apply(関数) — グループごとに関数を適用。時系列や地域別の集計でよく使います。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。6次元の産業特化指標を主成分分析(PCA)で低次元に圧縮し、都道府県間の類似性・差異を2次元空間に投影する。各主成分の「因子負荷量(Factor Loadings)」を解釈することで、産業構造の主要な変動パターンを明らかにする。
| 指標 | PC1 負荷量 | PC2 負荷量 |
|---|---|---|
| 観光特化 | -0.348 | -0.162 |
| 農業特化代理 | +0.474 | -0.037 |
| 教育特化 | +0.491 | +0.300 |
| 医療特化 | -0.018 | +0.854 |
| 建設特化代理 | +0.501 | -0.028 |
| 消費支出_log | +0.402 | -0.389 |
PC1(寄与率39.7%):正方向に農業・教育・建設特化、負方向に観光特化。地域の「生活基盤型産業 vs 観光特化型」の軸。PC2(寄与率20.1%):医療特化が強く正に寄与。「医療・福祉集積」の軸。累積寄与率(PC1+PC2):59.8%。
PCAは多変量データの分散を最大化する方向(主成分)を順次抽出する。因子負荷量の絶対値が大きい変数ほどその主成分に強く寄与する。biplot(スコアプロット+負荷量矢印)で変数間関係と観測値の分布を同時に可視化できる。
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | print('\n=== Fig2: PCAスコアプロット ===') fig, ax = plt.subplots(figsize=(11, 8)) for region in REGION_ORDER: mask_r = df_clean['地域'].values == region if mask_r.sum() == 0: continue ax.scatter(scores[mask_r, 0], scores[mask_r, 1], color=REGION_COLORS[region], s=80, alpha=0.85, label=region, zorder=3) for idx in np.where(mask_r)[0]: pref = df_clean['都道府県'].iloc[idx] ax.annotate(pref, (scores[idx, 0], scores[idx, 1]), fontsize=7, xytext=(4, 3), textcoords='offset points', color=REGION_COLORS[region]) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。138 139 140 141 142 143 144 145 146 147 | # 原点に十字線 ax.axhline(0, color='gray', linewidth=0.6, linestyle='--', alpha=0.5) ax.axvline(0, color='gray', linewidth=0.6, linestyle='--', alpha=0.5) ax.set_xlabel(f'PC1(寄与率 {ev_ratio[0]*100:.1f}%)', fontsize=12) ax.set_ylabel(f'PC2(寄与率 {ev_ratio[1]*100:.1f}%)', fontsize=12) ax.set_title('主成分分析(PCA)スコアプロット\n産業特化指標の都道府県別分布(2022年)', fontsize=13, fontweight='bold') ax.legend(title='地域ブロック', bbox_to_anchor=(1.01, 1), loc='upper left', fontsize=9, title_fontsize=9) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。{値:.2f}(小数2桁)、{値:,}(3桁区切り)、{値:>10}(右寄せ10桁)など、覚えると出力が一気に整います。148 149 150 151 152 153 154 155 156 157 158 159 | # 因子負荷量の矢印(biplot) scale_factor = 2.5 for j, v in enumerate(VARS): lx, ly = loadings[0, j] * scale_factor, loadings[1, j] * scale_factor ax.annotate('', xy=(lx, ly), xytext=(0, 0), arrowprops=dict(arrowstyle='->', color='#E53935', lw=1.5)) ax.text(lx * 1.08, ly * 1.08, v.replace('代理', '代理\n').replace('特化', '特化\n'), fontsize=8, color='#E53935', ha='center') ax.grid(True, alpha=0.3) plt.tight_layout() save_fig('fig2_pca') |
=== Fig2: PCAスコアプロット === → html/figures/2021_U3_fig2_pca.png 保存完了
plt.subplots(figsize=(W, H)) で図サイズ指定、fig.savefig(..., bbox_inches='tight') で余白を自動で詰めて保存。標準化した6次元の産業特化指標をWard法(Ward's hierarchical clustering)でクラスタリングする。Ward法は各クラスタ内分散の増加を最小化するようにクラスタを統合するため、均質なグループを形成しやすい。デンドログラムから適切なクラスタ数を視覚的に判断する。
| クラスタ | 主な都道府県(例) | 産業特化プロファイル | 政策的特徴 |
|---|---|---|---|
| Cluster A | 北海道・沖縄 | 観光特化が顕著に高い | 観光振興・インバウンド政策が核心 |
| Cluster B | 東京都・大阪府・愛知県等 | 教育特化・消費支出高水準 | 大都市圏:高等教育・知識産業の集積 |
| Cluster C | 東北・山陰等地方圏 | 農業特化代理が相対的に高い | 第一次産業の維持・農業活性化施策 |
| Cluster D | その他地方都市圏 | 医療特化・建設特化が中程度 | 地方中核都市:医療・住宅整備が重要 |
Ward法は階層的クラスタリングの一手法で、統合時のクラスタ内二乗和増分を最小化する。デンドログラムの「大きな距離ジャンプ」がある箇所でカットすると適切なクラスタ数が得られる("elbow" 判断)。
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | print('\n=== Fig3: Ward法デンドログラム ===') linked = linkage(X_scaled, method='ward') fig, ax = plt.subplots(figsize=(14, 6)) dend = dendrogram( linked, labels=df_clean['都道府県'].values, ax=ax, leaf_rotation=90, leaf_font_size=8, color_threshold=0.7 * max(linked[:, 2]), ) ax.set_title('Ward法階層クラスタリング デンドログラム\n産業特化指標による都道府県類型(2022年)', fontsize=13, fontweight='bold') ax.set_xlabel('都道府県', fontsize=11) ax.set_ylabel('非類似度(Ward距離)', fontsize=11) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。{値:.2f}(小数2桁)、{値:,}(3桁区切り)、{値:>10}(右寄せ10桁)など、覚えると出力が一気に整います。180 181 182 183 184 185 186 187 188 189 190 191 192 | # k=4 でカットする水準を示す補助線 # Ward距離の上位ギャップを探してカット点を示す sorted_dist = np.sort(linked[:, 2]) gaps = np.diff(sorted_dist) # 上位5ギャップのうち最大を採用(k=4カット) n_clusters_target = 4 cutoff_height = (linked[-n_clusters_target + 1, 2] + linked[-n_clusters_target, 2]) / 2 ax.axhline(y=cutoff_height, color='red', linestyle='--', linewidth=1.5, label=f'k={n_clusters_target} クラスタ分割線') ax.legend(fontsize=9) plt.tight_layout() save_fig('fig3_dendro') |
=== Fig3: Ward法デンドログラム === → html/figures/2021_U3_fig3_dendro.png 保存完了
ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。plt.subplots(figsize=(W, H)) で図サイズ指定、fig.savefig(..., bbox_inches='tight') で余白を自動で詰めて保存。観光特化指標(旅館施設密度)と消費支出(家計消費水準)の関係をクロスセクション分析する。特化係数が高い(観光産業が特化している)都道府県では、消費活動水準が高い(または低い)かを検証し、産業集積と経済成長の関係を考察する。
| 指標の組み合わせ | 相関係数 r | p値 | 有意水準 | 解釈 |
|---|---|---|---|---|
| 観光特化 × 消費支出 | -0.316 | 0.031 | * (p<0.05) | 観光特化地域ほど消費支出が低い傾向(負の相関) |
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import matplotlib.patches as mpatches import numpy as np import pandas as pd from sklearn.preprocessing import StandardScaler from sklearn.decomposition import PCA from scipy.cluster.hierarchy import dendrogram, linkage from scipy import stats import warnings warnings.filterwarnings('ignore') 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') — グラフを画面表示せずファイルに保存するためのおまじない。os.makedirs('html/figures', exist_ok=True) — 図の保存先フォルダを作る(既にあってもOK)。StandardScaler().fit_transform(X) — 各列を「平均0・分散1」に標準化。単位が違う変数のβを比較可能に。f"...{x}..." はf-string。文字列の中に {変数} と書くだけで埋め込めて、{x:.2f} のように書式も指定できます。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 | REGION_MAP = { '北海道': '北海道', '青森県': '東北', '岩手県': '東北', '宮城県': '東北', '秋田県': '東北', '山形県': '東北', '福島県': '東北', '茨城県': '関東', '栃木県': '関東', '群馬県': '関東', '埼玉県': '関東', '千葉県': '関東', '東京都': '関東', '神奈川県': '関東', '新潟県': '中部', '富山県': '中部', '石川県': '中部', '福井県': '中部', '山梨県': '中部', '長野県': '中部', '岐阜県': '中部', '静岡県': '中部', '愛知県': '中部', '三重県': '近畿', '滋賀県': '近畿', '京都府': '近畿', '大阪府': '近畿', '兵庫県': '近畿', '奈良県': '近畿', '和歌山県': '近畿', '鳥取県': '中国・四国', '島根県': '中国・四国', '岡山県': '中国・四国', '広島県': '中国・四国', '山口県': '中国・四国', '徳島県': '中国・四国', '香川県': '中国・四国', '愛媛県': '中国・四国', '高知県': '中国・四国', '福岡県': '九州・沖縄', '佐賀県': '九州・沖縄', '長崎県': '九州・沖縄', '熊本県': '九州・沖縄', '大分県': '九州・沖縄', '宮崎県': '九州・沖縄', '鹿児島県': '九州・沖縄', '沖縄県': '九州・沖縄', } REGION_COLORS = { '北海道': '#E53935', '東北': '#FB8C00', '関東': '#43A047', '中部': '#1E88E5', '近畿': '#8E24AA', '中国・四国': '#00ACC1', '九州・沖縄': '#6D4C41', } REGION_ORDER = ['北海道', '東北', '関東', '中部', '近畿', '中国・四国', '九州・沖縄'] |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | print('\n=== PCA ===') X_raw = df_clean[VARS].values scaler = StandardScaler() X_scaled = scaler.fit_transform(X_raw) pca = PCA(n_components=min(len(VARS), len(df_clean))) scores = pca.fit_transform(X_scaled) loadings = pca.components_ # shape: (n_components, n_vars) ev_ratio = pca.explained_variance_ratio_ print('寄与率:') for i, ev in enumerate(ev_ratio[:4]): print(f' PC{i+1}: {ev*100:.1f}% (累積: {ev_ratio[:i+1].sum()*100:.1f}%)') # 因子負荷量 print('\n--- 因子負荷量(PC1, PC2)---') for j, v in enumerate(VARS): print(f' {v:12s}: PC1={loadings[0,j]:+.3f}, PC2={loadings[1,j]:+.3f}') |
=== PCA === 寄与率: PC1: 39.7% (累積: 39.7%) PC2: 20.1% (累積: 59.8%) PC3: 15.1% (累積: 75.0%) PC4: 10.5% (累積: 85.5%) --- 因子負荷量(PC1, PC2)--- 観光特化 : PC1=-0.348, PC2=-0.162 農業特化代理 : PC1=+0.474, PC2=-0.037 教育特化 : PC1=+0.491, PC2=+0.300 医療特化 : PC1=-0.018, PC2=+0.854 建設特化代理 : PC1=+0.501, PC2=-0.028 消費支出_log : PC1=+0.402, PC2=-0.389
StandardScaler().fit_transform(X) — 各列を「平均0・分散1」に標準化。単位が違う変数のβを比較可能に。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。261 262 263 264 265 266 267 268 | print('\n=== Fig4: 観光特化 vs 消費支出 散布図 ===') x_plot = df_clean['観光特化'].values y_plot = df_clean['消費支出(二人以上の世帯)'].values / 1000 # 千円単位 # 相関係数 r_val, p_val = stats.pearsonr(x_plot, y_plot) print(f'相関係数: r={r_val:.4f}, p={p_val:.4f}') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。plt.subplots(figsize=(W, H)) で図サイズ指定、fig.savefig(..., bbox_inches='tight') で余白を自動で詰めて保存。269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | # 回帰直線 slope, intercept, _, _, stderr = stats.linregress(x_plot, y_plot) x_fit = np.linspace(x_plot.min(), x_plot.max(), 100) y_fit = slope * x_fit + intercept fig, ax = plt.subplots(figsize=(10, 7)) for region in REGION_ORDER: mask_r = df_clean['地域'].values == region if mask_r.sum() == 0: continue ax.scatter(x_plot[mask_r], y_plot[mask_r], color=REGION_COLORS[region], s=80, alpha=0.85, label=region, zorder=3) for idx in np.where(mask_r)[0]: pref = df_clean['都道府県'].iloc[idx] ax.annotate(pref, (x_plot[idx], y_plot[idx]), fontsize=7, xytext=(4, 3), textcoords='offset points', color=REGION_COLORS[region]) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。stats.linregress(x, y) — 単回帰の傾き・切片・r値・p値・標準誤差を返します。使わない値は _ で受け取り。.dropna() は欠損行を除去、.copy() は独立したコピーを作る。pandasで警告を防ぐ定石。289 290 291 292 293 294 295 296 297 298 299 300 | # 回帰直線 line_style = '-' if p_val < 0.05 else '--' ax.plot(x_fit, y_fit, color='black', linewidth=1.8, linestyle=line_style, label=f'回帰直線 (r={r_val:.3f}, p={p_val:.3f})') ax.set_xlabel('観光特化指標(旅館施設数/万人)', fontsize=12) ax.set_ylabel('消費支出(千円, 二人以上世帯)', fontsize=12) ax.set_title('観光産業集積と消費支出水準の関係(2022年)\n都道府県別クロスセクション分析', fontsize=13, fontweight='bold') ax.legend(title='地域ブロック', bbox_to_anchor=(1.01, 1), loc='upper left', fontsize=9, title_fontsize=9) ax.grid(True, alpha=0.3) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。f"...{x}..." はf-string。文字列の中に {変数} と書くだけで埋め込めて、{x:.2f} のように書式も指定できます。301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | # 相関注釈 sig_str = '**' if p_val < 0.01 else ('*' if p_val < 0.05 else 'n.s.') ax.text(0.05, 0.95, f'r = {r_val:.3f} {sig_str}\np = {p_val:.3f}\nN = {len(df_clean)}', transform=ax.transAxes, fontsize=10, verticalalignment='top', bbox=dict(boxstyle='round', facecolor='lightyellow', alpha=0.8)) plt.tight_layout() save_fig('fig4_scatter') print('\n=== 全図の保存完了 ===') print('Fig1: 産業特化指標レーダーチャート(地域ブロック別)') print('Fig2: PCAスコアプロット(都道府県ラベル付き biplot)') print('Fig3: Ward法クラスタリング デンドログラム') print('Fig4: 観光特化 vs 消費支出 散布図(2022年)') |
=== Fig4: 観光特化 vs 消費支出 散布図 === 相関係数: r=-0.3155, p=0.0308 → html/figures/2021_U3_fig4_scatter.png 保存完了 === 全図の保存完了 === Fig1: 産業特化指標レーダーチャート(地域ブロック別) Fig2: PCAスコアプロット(都道府県ラベル付き biplot) Fig3: Ward法クラスタリング デンドログラム Fig4: 観光特化 vs 消費支出 散布図(2022年)
df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。| データ | 出典 | 備考 |
|---|---|---|
| SSDSE-B-2026.csv | 統計数理研究所 SSDSE(社会・人口統計体系データセット) | 2022年度・47都道府県 |
| 旅館営業施設数(ホテルを含む) | 観光庁 宿泊旅行統計調査 | 観光特化の代理変数 |
| 大学学生数・一般病院数・診療所数 | 文部科学省・厚生労働省(SSDSE-B 収録) | 教育・医療特化の代理変数 |
| 1人1日当たりごみ排出量 | 環境省 一般廃棄物排出・処理状況調査 | 農業特化代理の基礎データ |
| 消費支出(二人以上の世帯) | 総務省 家計調査(SSDSE-B 収録) | 経済成長の代理変数 |
本教育用コードはSSDE-B-2026の実データを使用。合成データ・乱数生成(np.random.seed等)は一切使用しない。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。