この教材は原論文と同じデータを読み込み、同じ手順で計算し直しています。画面に出る数値と図は、あなたのブラウザがその場で計算した結果です。
| 原論文が使ったデータ | 論文本文からは特定できなかった 分析単位:市区町村 中核手法:相関分析・ガウシアングラフィカルモデル・ネットワーク分析・グラフィカル lasso |
|---|---|
| この教材が使うデータ |
|
| 原論文(PDF) | 地方創生目標指標に関する変化要因ネットワークの推定とそれに基づく地域間連携策の提案 総務大臣賞/張 瀚天、白鳥 友風(筑波大学大学院システム情報工学研究科) |
▶ ここに書いてある分析は、ページ下部の「🐍 ブラウザで動かす」でそのまま実行できます(インストール不要)。動かしているのは code/2019_U1_daijin.py(233 行)そのものです。
このページの手法デモを自分で動かすには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
※ 原論文は SSDSE-2019A・e-Stat・RESAS を統合した2010年→2015年の「変化数」データ(1722市町村)を分析しました。現在配布中の SSDSE には 2010年・2015年の市町村値も RESAS の特化係数も収録されていないため、本ページの図1は原論文の報告値の可視化(再計算ではない)、図2〜図4は現行 SSDSE-A-2025 の水準値を使った手法デモです(詳細は「データと目標指標」の再現範囲を参照)。
日本の人口減少・少子高齢化は、特に地方において深刻である。原論文の指摘によれば、東京・埼玉・千葉・神奈川の人口の合計は2015年で日本の約28.4%を占め、2010年の約27.8%から0.6ポイント(約51万3千人)増加した——地方から大都市圏への人口流出が続いている。この課題に歯止めをかけるため、内閣府地方創生推進事務局は2015年に第1期「まち・ひと・しごと創生総合戦略」を策定し、「地方創生」を達成するための4つの基本目標を設定した。
| 基本目標 | 内容 |
|---|---|
| 目標1 | 地方に仕事をつくり、安心して働けるようにする |
| 目標2 | 地方への新しいひとの流れをつくる |
| 目標3 | 若い世代の結婚・出産・子育ての希望をかなえる |
| 目標4 | 時代にあった地域をつくり、安心なくらしを守るとともに、地域と地域を連携する |
これらの達成度を定量的に評価するため、基本目標に対して15件、施策に対して116件の KPI(key performance indicator)が設定されている。また取り組みの1つとして「連携中核都市圏構想」(平成26年度から展開、2019年9月時点で32圏域が宣言)があるが、先行研究では圏内に含まれない地域の存在や、圏外から圏内への人口流出を助長する可能性が指摘されている。
さらに厄介なのは、基本目標が互いに独立に達成しうるものではないことである。例えば目標1に関連する地域産業の「付加価値額」は目標2に関連する「人口流出率」と相関し、同時に「人口流入率」と「所得水準」にも相関がある——人口と所得水準は循環して影響しあう。民間企業・自治体・地域間連携など複数の主体の要因が複雑に絡み合うなかで、各自治体は「具体的に何を改善すれば基本目標の達成につながるのか」が不透明な状況に置かれている。
ガウシアングラフィカルモデル グラフィカルlasso 媒介中心性 潜在クラス分析 SSDSE-A
原論文は、市町村に対して広範な変数を収録する SSDSE-2019A(独立行政法人統計センターの教育用標準データセット・市区町村データ)を軸に、5年(2010年→2015年)の変化に着目するため e-Stat から取得した変数、および RESAS(地域経済分析システム)の特化係数・売上金額を、市町村のユニークな id である地域コードで統合した。欠損を除いた 1722市町村が分析対象である。
4つの基本目標の KPI に深く関連する10項目を「目標指標」として定義した。
| 基本目標 | 目標指標 |
|---|---|
| 目標1(しごと) | 就業者数・女性就業者数・完全失業者数・正規雇用者数(4変数) |
| 目標2(ひとの流れ) | 転入者数・転出者数・転出超過数(3変数) |
| 目標3(結婚・出産・子育て) | 婚姻件数・出生数・保育所等数(3変数) |
| 目標4(地域づくり・地域間連携) | 設定せず——KPI が「立地適正化計画を作成する市町村数」など市町村にまたがる項目が多く単一市町村の分析になじまないこと、収集できるデータの限界のため |
都市部への人口流出が続くなか、「すでに人口規模が大きいところほど目標指標を改善しやすいのではないか?」という疑問がまず浮かぶ。もしそうなら、大都市と過疎地域では処方箋がまったく別になる。分析1では、2010年総人口と各目標指標の増加率(2010→2015年)の相関を確認する。
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | import os import numpy as np import pandas as pd import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import networkx as nx from sklearn.covariance import GraphicalLasso plt.rcParams['font.family'] = 'Hiragino Sans' plt.rcParams['axes.unicode_minus'] = False plt.rcParams['figure.dpi'] = 150 FIG_DIR = 'html/figures' DATA_A = 'data/raw/SSDSE-A-2025.csv' os.makedirs(FIG_DIR, exist_ok=True) |
print はしません。ライブラリと保存先の設定だけ。次のステップへ進みましょう。networkx — ネットワーク(グラフ)の構築・媒介中心性の計算・描画を担うライブラリ。sklearn.covariance.GraphicalLasso — グラフィカルlasso(スパースな精度行列の推定)の実装。原論文はRのglassoパッケージ相当の手法を用いた。matplotlib.use('Agg') — 画面表示せずファイルに保存するための設定。from ライブラリ import クラス — 長い名前空間を省略してクラスを直接呼べる。使うものだけを import するとコードの依存関係が読みやすくなります。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 | # ===== ステップ1: 図1 原論文 図表3 の相関係数(報告値)の可視化 ===== # 原論文 図表3: 2010年総人口と各目標指標の増加率(2010→2015年)の相関係数。 # 以下の数値は原論文 図表3 に記載の報告値の転記であり、再計算ではない。 paper_corr = { '就業者増加率': 0.127, '女性就業者増加率': 0.149, '完全失業者増加率': 0.097, '正規雇用者増加率': 0.059, '転出増加率': 0.036, '転入増加率': 0.068, '転出超過増加率': -0.047, '婚姻件数増加率': -0.0046, '出生数増加率': 0.027, '保育所等増加率': 0.012, } fig, ax = plt.subplots(figsize=(9, 4.8)) names = list(paper_corr.keys()) vals = [paper_corr[k] for k in names] colors = ['#1565C0' if v >= 0 else '#C62828' for v in vals] ax.barh(range(len(names))[::-1], vals, color=colors, height=0.6) ax.set_yticks(range(len(names))[::-1]) ax.set_yticklabels(names, fontsize=10) ax.axvline(0, color='#555', lw=0.8) ax.axvline(0.2, color='#999', lw=0.8, ls='--') ax.axvline(-0.2, color='#999', lw=0.8, ls='--') ax.set_xlim(-0.25, 0.25) ax.set_xlabel('2010年総人口との相関係数(原論文 図表3 の報告値)') ax.set_title('分析1: 目標指標の増加率と人口規模の相関\n' '(原論文 図表3 の報告値の可視化。再計算ではない)', fontsize=11) for i, v in zip(range(len(names))[::-1], vals): ax.text(v + (0.008 if v >= 0 else -0.008), i, f'{v:.3f}', va='center', ha='left' if v >= 0 else 'right', fontsize=9) fig.tight_layout() fig.savefig(f'{FIG_DIR}/2019_U1_fig1.png', bbox_inches='tight') plt.close(fig) print('【図1】原論文 図表3 の報告値(2010年総人口と増加率の相関係数)') print(' 最大: 女性就業者増加率 r=0.149 / 最小: 転出超過増加率 r=-0.047') print(' → いずれも |r|<0.2 で、人口規模は増加率にほぼ影響しない(原論文の結論)') |
【図1】原論文 図表3 の報告値(2010年総人口と増加率の相関係数) 最大: 女性就業者増加率 r=0.149 / 最小: 転出超過増加率 r=-0.047 → いずれも |r|<0.2 で、人口規模は増加率にほぼ影響しない(原論文の結論)
paper_corr の10個の数値は原論文 図表3 に記載された報告値の転記です(2010年・2015年の市町村値が現行SSDSEにないため再計算はできません)。ax.barh(y, vals) は横棒グラフ。range(len(names))[::-1] のように [::-1] で逆順にすると、辞書の並び順を上から下へ表示できます。
分析2で使うガウシアングラフィカルモデル(GGM)は、変数が多変量正規分布に従うことを仮定する。ところが市町村の規模の変数(就業者数など)は、少数の大都市が極端に大きい値をとる裾の重い分布(ベキ分布)をしている。原論文は分析1の結果(増加率は人口規模によらない)を踏まえ、2010年と2015年の差(変化数)を2010年の総人口で割って「一人当たり」の値にすることで、分布を正規分布に近づけた(原論文 図表2)。
ここでは同じ変換の効果を、現行 SSDSE-A-2025 の水準値で体験する(原論文が扱ったのは変化数である点に注意)。
69 70 71 72 73 | # ===== ステップ2: SSDSE-A-2025 の読み込み(手法デモ用の現行データ) ===== raw = pd.read_csv(DATA_A, encoding='cp932', header=None, skiprows=3) raw.columns = pd.read_csv(DATA_A, encoding='cp932', header=None, nrows=3).iloc[2] print(f'\n【SSDSE-A-2025】{len(raw)}市区町村を読み込み' f'(原論文の SSDSE-2019A ベース1722市町村とは別の年次・版)') |
【SSDSE-A-2025】1741市区町村を読み込み(原論文の SSDSE-2019A ベース1722市町村とは別の年次・版)
skiprows=3 でデータ本体を読み、3行目(日本語名)を列名として貼り直しています。pd.read_csv(..., header=None, nrows=3).iloc[2] — ヘッダーが複数行あるCSVは「ヘッダーだけ別に読む」テクニックが便利。75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | # ===== ステップ3: 図2 前処理デモ — ベキ分布を人口あたりに変換 ===== # 原論文 図表2: 就業者数の「変化数」がベキ分布 → 2010年人口で割って正規分布に近づけた。 # ここでは現行データの「水準値」で同じ変換の効果を体験する(変化数のデモではない)。 emp = raw['就業者数'].astype(float) emp_pc = emp / raw['総人口'].astype(float) fig, axes = plt.subplots(1, 2, figsize=(9.6, 3.8)) axes[0].hist(emp / 1e4, bins=120, color='#26A69A') axes[0].set_title('(a) 就業者数(万人): 裾の重い分布', fontsize=10.5) axes[0].set_xlabel('就業者数(万人)') axes[0].set_ylabel('市区町村数') axes[1].hist(emp_pc, bins=60, color='#26A69A') axes[1].set_title('(b) 就業者数 ÷ 総人口: 対称な分布に近づく', fontsize=10.5) axes[1].set_xlabel('就業者数 ÷ 総人口') fig.suptitle('前処理デモ: 原論文 図表2 と同じ「人口で割る」変換(SSDSE-A-2025 の水準値。' '原論文は2010→2015年の変化数に適用)', fontsize=10) fig.tight_layout(rect=[0, 0, 1, 0.90]) fig.savefig(f'{FIG_DIR}/2019_U1_fig2.png', bbox_inches='tight') plt.close(fig) print('\n【図2】前処理デモ(就業者数)') print(f' 変換前の歪度: {emp.skew():.2f} → 人口あたり変換後: {emp_pc.skew():.2f}') |
【図2】前処理デモ(就業者数) 変換前の歪度: 9.29 → 人口あたり変換後: 1.02
Series.skew() で歪度(skewness)を計算できます。0に近いほど左右対称。正規分布への近さの簡便なチェックに便利。
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 132 | # ===== ステップ4: 変数の構築(人口あたり変換と符号反転) ===== # 原論文にならい、規模の変数は総人口で割り、比率(%)の変数はそのまま使う。 goal_vars = ['就業者数', '就業者数(女)', '完全失業者数', '転入者数(日本人移動者)', '転出者数(日本人移動者)', '婚姻件数', '出生数', '保育所等数(基本票)'] # 目標指標(8個) other_cnt = ['15~64歳人口', '65歳以上人口', '死亡数', '事業所数(民営)', '従業者数(民営)', '歳入決算総額(市町村財政)', '歳出決算総額(市町村財政)', '地方税(市町村財政)', '民生費(市町村財政)', '教育費(市町村財政)', '災害復旧費(市町村財政)'] # 規模の変数 ratio_vars = ['経常収支比率(市町村財政)', '実質公債費比率(市町村財政)'] # 比率 X = pd.DataFrame(index=raw.index) pop = raw['総人口'].astype(float) for c in goal_vars + other_cnt: X[c] = raw[c].astype(float) / pop for c in ratio_vars: X[c] = raw[c].astype(float) X = X.dropna() X = X[pop.loc[X.index] > 0] # 多重共線性の確認(原論文は歳入・歳出・投資的経費が r>=0.9 → 歳出等を除外) r_in_out = X['歳入決算総額(市町村財政)'].corr(X['歳出決算総額(市町村財政)']) print(f'\n【変数の構築】n={len(X)}市区町村, {X.shape[1]}変数') print(f' 歳入決算総額 と 歳出決算総額 の相関: r={r_in_out:.3f}' ' → 原論文と同様ほぼ同一の変数とみなし歳出を除外') X = X.drop(columns=['歳出決算総額(市町村財政)']) # 符号の反転: 地方創生にとって「減ることが望ましい」変数に -1 を掛けて # 解釈を揃える(原論文 2.3節・3節の処理。原論文は変化数に適用) flip = ['完全失業者数', '転出者数(日本人移動者)', '死亡数', '経常収支比率(市町村財政)', '実質公債費比率(市町村財政)'] X[flip] = -X[flip] Z = (X - X.mean()) / X.std() # 標準化(平均0・分散1) short = {c: c.replace('(市町村財政)', '').replace('(日本人移動者)', '') .replace('(基本票)', '').replace('(民営)', '') for c in X.columns} print(f' 符号反転: {len(flip)}変数(完全失業者数・転出者数・死亡数・経常収支比率・実質公債費比率)') |
【変数の構築】n=1740市区町村, 21変数 歳入決算総額 と 歳出決算総額 の相関: r=0.999 → 原論文と同様ほぼ同一の変数とみなし歳出を除外 符号反転: 5変数(完全失業者数・転出者数・死亡数・経常収支比率・実質公債費比率)
X[flip] = -X[flip] — 列のリストを使えば複数列にまとめて演算を適用できます。目標指標は他の様々な要因と複雑に関係しあっている。単純な相関行列では、AとBの両方がCに引きずられて生じる「見かけの相関」が大量のエッジを作ってしまう。そこで原論文はガウシアングラフィカルモデル(GGM)を使い、変数 Xi と Xj の関係を「他のすべての変数を与えたうえでの条件付き分布」で推定してグラフ化した。GGMのモデルは次の式で表される(原論文 2.3節)。
ここで ωjk は説明変数の共分散行列の逆行列(精度行列)の (j,k) 要素である。ωjk = 0 と推定されれば「Xj と Xk は他の変数が与えられた下で独立」=「他の変数を考慮すると直接の関係はない」という条件付き独立として解釈できる。
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | # ===== ステップ5: glasso のハイパーパラメータを AIC で探索 ===== # 原論文は λ を 0〜0.5 の 0.001 刻みで探索し AIC 最小を選択。 # 本デモは 0.005〜0.5 の 0.005 刻み(計算時間短縮のため)。 n, p = Z.shape results = [] for alpha in np.arange(0.005, 0.5001, 0.005): try: gl = GraphicalLasso(alpha=alpha, max_iter=500).fit(Z.values) except Exception: continue k = (np.abs(gl.precision_[np.triu_indices(p, 1)]) > 1e-8).sum() + p aic = -2 * n * gl.score(Z.values) + 2 * k results.append((alpha, aic, k - p, gl)) best_alpha, best_aic, best_edges, best_gl = min(results, key=lambda t: t[1]) print(f'\n【glasso デモ】λ を {len(results)}通り探索(AIC 基準)') print(f' AIC 最小: λ={best_alpha:.3f}, AIC={best_aic:.1f}, エッジ数={best_edges}') print(' ※原論文は 0.001 刻みで探索し、変化数データに対して AIC 最小の λ を採用') |
【glasso デモ】λ を 100通り探索(AIC 基準) AIC 最小: λ=0.005, AIC=68800.1, エッジ数=164 ※原論文は 0.001 刻みで探索し、変化数データに対して AIC 最小の λ を採用
GraphicalLasso(alpha=λ) を当てはめ、λ を 0.005〜0.5 の0.005刻み(100通り)で動かします(原論文は 0〜0.5 の0.001刻み)。min(results, key=lambda t: t[1]) — タプルのリストから「2番目の要素が最小のもの」を1行で取り出せます。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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | # ===== ステップ6: 図3 推定されたネットワークの可視化(手法デモ) ===== # 偏相関 r_jk = -ω_jk / sqrt(ω_jj・ω_kk) をエッジの重みとする prec = best_gl.precision_ d = np.sqrt(np.diag(prec)) pcorr = -prec / np.outer(d, d) np.fill_diagonal(pcorr, 0.0) cols = list(Z.columns) G = nx.Graph() G.add_nodes_from(range(p)) for i in range(p): for j in range(i + 1, p): if abs(pcorr[i, j]) > 1e-4: G.add_edge(i, j, w=pcorr[i, j], dist=1.0 / abs(pcorr[i, j])) # 正・負それぞれの係数ネットワークで媒介中心性を計算し、差をとる(原論文 2.3節) Gp = nx.Graph() Gn = nx.Graph() Gp.add_nodes_from(range(p)) Gn.add_nodes_from(range(p)) for u, v, d_ in G.edges(data=True): (Gp if d_['w'] > 0 else Gn).add_edge(u, v, dist=d_['dist']) bc_p = nx.betweenness_centrality(Gp, weight='dist') bc_n = nx.betweenness_centrality(Gn, weight='dist') score = {i: bc_p.get(i, 0.0) - bc_n.get(i, 0.0) for i in range(p)} pos = nx.spring_layout(G, seed=42, k=1.4) fig, ax = plt.subplots(figsize=(9.6, 7.6)) sizes = [300 + 2600 * max(score[i], 0) for i in range(p)] node_col = ['#FFC107' if cols[i] in goal_vars else '#90CAF9' for i in range(p)] top3 = sorted(score, key=score.get, reverse=True)[:3] for i in top3: node_col[i] = '#F57F17' if cols[i] in goal_vars else '#1565C0' epos = [(u, v) for u, v, d_ in G.edges(data=True) if d_['w'] > 0] eneg = [(u, v) for u, v, d_ in G.edges(data=True) if d_['w'] < 0] nx.draw_networkx_edges(G, pos, edgelist=epos, edge_color='#78909C', width=[3 * abs(G[u][v]['w']) + 0.3 for u, v in epos], ax=ax) nx.draw_networkx_edges(G, pos, edgelist=eneg, edge_color='#E57373', style='dashed', width=[3 * abs(G[u][v]['w']) + 0.3 for u, v in eneg], ax=ax) nx.draw_networkx_nodes(G, pos, node_size=sizes, node_color=node_col, edgecolors='#455A64', ax=ax) nx.draw_networkx_labels(G, pos, labels={i: short[cols[i]] for i in range(p)}, font_size=8, font_family='Hiragino Sans', ax=ax) ax.set_title('glasso により推定した変数間ネットワーク(手法デモ: SSDSE-A-2025 の水準値, ' f'λ={best_alpha:.3f}, AIC最小)\n' '黄=目標指標系 / 青=その他 / 濃色=媒介中心性スコア上位3 / ' '実線=正・破線=負の偏相関(原論文 図表4(a) の再計算ではない)', fontsize=10) ax.axis('off') fig.tight_layout() fig.savefig(f'{FIG_DIR}/2019_U1_fig3.png', bbox_inches='tight') plt.close(fig) print(f'\n【図3】ネットワーク描画: ノード{p}個, 正エッジ{len(epos)}本, 負エッジ{len(eneg)}本') |
【図3】ネットワーク描画: ノード20個, 正エッジ96本, 負エッジ68本
nx.spring_layout(G, seed=42) — バネモデルによる自動レイアウト。seed を固定すると毎回同じ配置になり再現性が保てます。
ネットワークが推定できたら、次は「その構造の中でどの変数が最も影響を及ぼしているか」を評価したい。原論文は媒介中心性(betweenness centrality、Brandes 2001)を使う。媒介中心性は「あるノードが、他のノード間の最短距離のパスに含まれた回数」で評価され、どれだけ他の変数への影響を中継しているかを表す。
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 | # ===== ステップ7: 図4 媒介中心性スコア(正−負)の可視化(手法デモ) ===== order = sorted(range(p), key=lambda i: score[i]) fig, ax = plt.subplots(figsize=(8.6, 6.4)) vals4 = [score[i] for i in order] cols4 = ['#1565C0' if v >= 0 else '#C62828' for v in vals4] ax.barh(range(p), vals4, color=cols4, height=0.62) ax.set_yticks(range(p)) ax.set_yticklabels([short[cols[i]] for i in order], fontsize=9) ax.axvline(0, color='#555', lw=0.8) ax.set_xlabel('媒介中心性スコア(正の係数ネットワーク − 負の係数ネットワーク)') ax.set_title('手法デモ: 各変数の媒介中心性スコア(SSDSE-A-2025 の水準値)\n' '原論文 図表4(b) と同じ手順(距離=1/|係数|)。変化数分析の再計算ではない', fontsize=10.5) fig.tight_layout() fig.savefig(f'{FIG_DIR}/2019_U1_fig4.png', bbox_inches='tight') plt.close(fig) print('\n【図4】媒介中心性スコア(デモ)上位5変数:') for i in sorted(score, key=score.get, reverse=True)[:5]: print(f' {short[cols[i]]}: {score[i]:+.4f}') print('\n【原論文 4.2節の報告】媒介中心性が最も高かった変数(変化数, 順に):') print(' 市町村の一般財源, 15〜64歳人口, 課税対象所得, 地方税, 歳入決算額') print(' 負の値が大きい変数: 災害復旧費, 実質公債費比率, 経常収支比率') print(' → 経済規模の変化に関する変数群 =「稼ぐ力」が地方創生の出発点(原論文の結論)') print('\n=== 完了 ===') for i in range(1, 5): print(f'図{i}: html/figures/2019_U1_fig{i}.png') |
【図4】媒介中心性スコア(デモ)上位5変数: 歳入決算総額: +0.2398 就業者数: +0.1345 地方税: +0.0819 事業所数: +0.0760 従業者数: +0.0760 【原論文 4.2節の報告】媒介中心性が最も高かった変数(変化数, 順に): 市町村の一般財源, 15〜64歳人口, 課税対象所得, 地方税, 歳入決算額 負の値が大きい変数: 災害復旧費, 実質公債費比率, 経常収支比率 → 経済規模の変化に関する変数群 =「稼ぐ力」が地方創生の出発点(原論文の結論) === 完了 === 図1: html/figures/2019_U1_fig1.png 図2: html/figures/2019_U1_fig2.png 図3: html/figures/2019_U1_fig3.png 図4: html/figures/2019_U1_fig4.png
Gp と負のエッジだけのグラフ Gn で別々に媒介中心性を計算し(距離=1/|偏相関|)、差をスコアにします——原論文 2.3節とまったく同じ手順です。nx.betweenness_centrality(G, weight='dist') — weight にエッジ属性名を渡すと、重み付き最短経路で媒介中心性を計算します。
| 方向 | 変数(原論文 4.2節の報告、変化数) | 原論文の解釈 |
|---|---|---|
| 正の影響が大きい (上位5・順に) |
市町村の一般財源・15〜64歳人口・課税対象所得・地方税・歳入決算額の変化数 | 多くが自治体の経済規模の変化に関連する項目=中村良平(2018)の言う地方自治体の「稼ぐ力」。「稼ぐ力」が経済の好循環を生む出発点であるという考えと合致。 |
| 負の値が大きい | 災害復旧費・実質公債費比率・経常収支比率(の変化数) | 災害復旧費は災害に見舞われた地方で高くなるため、災害の影響から他の変数へ負の影響を与えていると考えられる。実質公債費比率・経常収支比率は分母と分子の与える影響がそれぞれ異なることが負の影響につながった可能性。 |
分析2で「稼ぐ力」の重要性が示された。それを向上させる案として原論文が注目したのが、基本目標4にもある「地方連携」である。理由は4つ(原論文 4.2節)。
| # | 地域間連携を考える理由 |
|---|---|
| 1 | 地域によって得意とする産業や環境が異なる——同様の状況にある自治体と連携することで、それぞれの状況に適した案を創出できる |
| 2 | 今後の人口減少傾向の下では、地域間で連携して経済規模を担保することが必要(15〜64歳人口の変化量はネットワークで2番目に正の影響) |
| 3 | 現在の連携中核都市圏構想では広域連携が難しい地域が多数存在する——近隣に限らない連携の枠組みが必要 |
| 4 | 海外に向けての「稼ぐ力」の向上——輸出には企業・産業の規模が関係する(Wagner 2007)ため、規模の獲得にも連携が有効 |
潜在クラス分析は、離散変数の尤度を EMアルゴリズムで最大化し、類似した変数の傾向をもつサンプルを共通のクラスターに分類する手法である(実装は R の poLCA が代表例;Linzer & Lewis 2011)。glasso と同じく尤度を用いる手法なので、クラスタ数をAICで客観的に決められる点、結果が所属確率で返るため各市町村が複数のクラスターに所属しうる(ソフトクラスタリング)点が、この研究の目的——柔軟な地方連携の提案——に合っている。原論文はクラスタ数を2〜50の間で探索し、AIC最小の24クラスタを採用した。
本研究は SSDSE-2019A・e-Stat・RESAS を統合した1722市町村のデータから、地方創生の目標指標に関する変化要因ネットワークを推定し、それに基づく地域間連携策を提案した。
| 限界 | 内容と今後 |
|---|---|
| 収集できるデータの限界 | 市町村単位のデータでは不足する変数が存在した可能性。5年でなく1年ごとの変化や、4つの目標に即した施策の有無などの変数が加わればより詳細で精緻な分析ができる。分析3の特化係数の欠損(秘匿)も同様。 |
| 将来のデータに対する妥当性 | 使用データは2016年以前が多く、地方創生への取り組みがまだ多くなかった時期のもの。様々な介入が行われた後の第2期総合戦略に対してこの結果がどれほど一般性をもつかは検証が必要。ただし分析自体はデータを変えることで更新でき、最新の国勢調査などの結果で分析をアップデートできる。 |
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 | # ===== ステップ7: 図4 媒介中心性スコア(正−負)の可視化(手法デモ) ===== order = sorted(range(p), key=lambda i: score[i]) fig, ax = plt.subplots(figsize=(8.6, 6.4)) vals4 = [score[i] for i in order] cols4 = ['#1565C0' if v >= 0 else '#C62828' for v in vals4] ax.barh(range(p), vals4, color=cols4, height=0.62) ax.set_yticks(range(p)) ax.set_yticklabels([short[cols[i]] for i in order], fontsize=9) ax.axvline(0, color='#555', lw=0.8) ax.set_xlabel('媒介中心性スコア(正の係数ネットワーク − 負の係数ネットワーク)') ax.set_title('手法デモ: 各変数の媒介中心性スコア(SSDSE-A-2025 の水準値)\n' '原論文 図表4(b) と同じ手順(距離=1/|係数|)。変化数分析の再計算ではない', fontsize=10.5) fig.tight_layout() fig.savefig(f'{FIG_DIR}/2019_U1_fig4.png', bbox_inches='tight') plt.close(fig) print('\n【図4】媒介中心性スコア(デモ)上位5変数:') for i in sorted(score, key=score.get, reverse=True)[:5]: print(f' {short[cols[i]]}: {score[i]:+.4f}') print('\n【原論文 4.2節の報告】媒介中心性が最も高かった変数(変化数, 順に):') print(' 市町村の一般財源, 15〜64歳人口, 課税対象所得, 地方税, 歳入決算額') print(' 負の値が大きい変数: 災害復旧費, 実質公債費比率, 経常収支比率') print(' → 経済規模の変化に関する変数群 =「稼ぐ力」が地方創生の出発点(原論文の結論)') print('\n=== 完了 ===') for i in range(1, 5): print(f'図{i}: html/figures/2019_U1_fig{i}.png') |
【図4】媒介中心性スコア(デモ)上位5変数: 歳入決算総額: +0.2398 就業者数: +0.1345 地方税: +0.0819 事業所数: +0.0760 従業者数: +0.0760 【原論文 4.2節の報告】媒介中心性が最も高かった変数(変化数, 順に): 市町村の一般財源, 15〜64歳人口, 課税対象所得, 地方税, 歳入決算額 負の値が大きい変数: 災害復旧費, 実質公債費比率, 経常収支比率 → 経済規模の変化に関する変数群 =「稼ぐ力」が地方創生の出発点(原論文の結論) === 完了 === 図1: html/figures/2019_U1_fig1.png 図2: html/figures/2019_U1_fig2.png 図3: html/figures/2019_U1_fig3.png 図4: html/figures/2019_U1_fig4.png
原論文の使用データ:SSDSE-2019A(独立行政法人統計センター・教育用標準データセット 市区町村データ)、e-Stat、RESAS——地域コードで統合、欠損を除く1722市町村
原論文の分析手法:相関分析、ガウシアングラフィカルモデル(グラフィカルlasso、λはAICで選択)、媒介中心性(正負ネットワーク分離)、潜在クラス分析(クラスタ数2〜50をAICで探索→24)
本ページのデモ:SSDSE-A-2025(1740市区町村・20変数の水準値)に同じ手順を適用(scikit-learn GraphicalLasso・networkx)
対象論文:2019年度(令和元年度)統計データ分析コンペティション 総務大臣賞(大学生・一般の部) 張 瀚天・白鳥 友風(筑波大学大学院 システム情報工学研究科 社会工学専攻)
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
lingam パッケージ)を適用し、glasso のエッジと向きつきエッジを比較する。(2)非正規性・非巡回性などの仮定が市町村データで妥当かを検討する。(3)結論がどの仮定に依存しているかを整理する。学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本ページのスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
GraphicalLasso(alpha=...) の λ を 0.01・0.05・0.1・0.3 に固定して図3を描き直してください。
本論文で学んだ手法(グラフィカルモデル・中心性・潜在クラス分析)は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。
この論文を理解できたか、クリックで確認しましょう。間違えても解説が出ます。
このページの分析は、この画面の中でそのまま実行できます。
Python をインストールする必要も、CSV をダウンロードする必要もありません。
下のセルの 「▶ ブラウザで実行」 を上から順に押すか、
「▶ 最初から全部実行」 で一気に流してください。
表示されるのは、本文の図表とまったく同じ計算の結果です
(動かしているのは再現スクリプト code/2019_U1_daijin.py そのもの)。
コードは書き換えられます。「✏️ 書き換える」で数字や変数を変えて ▶ を押すと、 結果がどう変わるかをその場で確かめられます(元に戻すボタンつき)。 ページを開いた時点で裏で実行環境の準備が始まっているので、待ち時間はほとんどありません。 初回だけ実行環境の取得にインターネット接続が必要です。