政策評価論文や因果推論教科書で、 こんな表現を見たはずです:
これが 回帰不連続デザイン (RDD)。 ランダム化実験ができない政策・社会現象で、 「閾値で処置が機械的に決まる」 制度を逆手に取って因果推論する手法です。 Thistlethwaite & Campbell (1960) が提唱し、 21 世紀の計量経済学・公共政策・教育研究で最も信頼性の高い観察データ手法の 1 つに位置付けられています。
statsmodels や rdrobust パッケージで局所線形回帰例1:合格・不合格のすぐ近く。 大学入試で合格点が 60 点。 59 点と 61 点の受験者は、 学力上ほぼ同等です(運の差)。 しかし片方は合格して大学に入る、 もう片方は不合格。 5 年後の年収を比べれば、 「大学進学の因果効果」が推定できる。
例2:人口 5 万人を境に「町」→「市」。 日本では人口 5 万人以上の自治体が「市」になります。 49,500 人の町と 50,500 人の市は人口規模としてほぼ同じですが、 市制施行に伴う権限・財源・自治体構造が大きく違う。 閾値前後の自治体を比べれば「市制の効果」が見える。
例3:選挙の得票率 50%。 与党候補が 50.1% で当選、 50.0% で落選。 結果の僅差は偶然と見做せる。 当選した候補の選挙区とそうでない選挙区で、 翌年の公共投資額を比べると「与党議員がいることの財政効果」が推定可能。
RDD では閾値から遠い対象は使いません。 例えば「人口 5 万人で市」 の場合、 1000 人の村と 100 万人の大都市を比べても市制の効果は分かりません(規模が違いすぎる)。 RDD は閾値の前後 ±数千人 のような狭い帯域を取り出して、 そこの不連続なジャンプを測ります。 帯域の中では「人口でほぼ同じ → 処置のみが違う → 実験に近い比較ができる」というロジック。
結果変数 Y(例:1人当たり地方交付税)
│
│ ★
│ ★ ★ ★
│ ★ ★ ★ ★
│ ★ ★
│ ★ ↕ τ (因果効果)
│ ────────────────────●──────────
│ ○ │
│ ○ ○ │
│ ○ │
│ ○ │
│___________________ c (閾値) _________→ X(人口)
│ 「町」 「市」
○(処置を受けない側)の連続的な傾向と、 ★(処置を受ける側)の連続的な傾向に、 閾値 $c$ でジャンプがある。 このジャンプの大きさ τ が、 因果効果の推定値です。
もし処置以外のすべての要因が $X$(強制変数、 running variable)に対して連続的に変化する(=ジャンプしない)なら、 $X = c$ でだけ起きるジャンプは処置効果以外ありえない。 これが RDD の identification の核心。 「連続性仮定」を満たすことが鍵です。
実務上は閾値近傍 $|X_i - c| \le h$(帯域幅 $h$)のサンプルを使い、 線形回帰:
帯域幅 $h$ を狭くするほど「閾値での効果」に近づく(バイアス小)が、 サンプルが減って分散大。 逆に広くすると分散小だがバイアス大。 トレードオフを最適化する自動選択法として:
Python の rdrobust パッケージは CCT 法をデフォルトで使う。
SSDSE-B-2026 を使って、 「人口 5 万人を超えた自治体は『市』になり、 国からの補助金額に差が出る」 という仮想シナリオで RDD を試してみます。 ※実際の地方自治法の市制施行要件は複雑ですが、 ここでは教育用に簡略化します。
SSDSE-B から、 人口 25,000〜100,000 人の自治体だけ取り出します(閾値 $c = 50000$ の±50,000 人)。 仮に該当する 12 自治体の値が以下だったとします(教育用の数値例):
| 自治体名(仮) | 人口 $X_i$ | 処置 $D_i$ | $X_i - c$ | 1人当たり交付税 $Y_i$(万円) |
|---|---|---|---|---|
| A 町 | 28,000 | 0 | −22,000 | 12.5 |
| B 町 | 34,000 | 0 | −16,000 | 11.8 |
| C 町 | 41,000 | 0 | −9,000 | 10.9 |
| D 町 | 45,000 | 0 | −5,000 | 10.3 |
| E 町 | 48,500 | 0 | −1,500 | 10.0 |
| F 町 | 49,800 | 0 | −200 | 9.8 |
| ⬆️ 閾値 50,000 人 ⬇️ | ||||
| G 市 | 50,300 | 1 | +300 | 12.5 |
| H 市 | 51,800 | 1 | +1,800 | 12.2 |
| I 市 | 54,000 | 1 | +4,000 | 11.8 |
| J 市 | 62,000 | 1 | +12,000 | 11.0 |
| K 市 | 78,000 | 1 | +28,000 | 10.0 |
| L 市 | 95,000 | 1 | +45,000 | 9.0 |
閾値直近のペア F 町(49,800 人, Y = 9.8)と G 市(50,300 人, Y = 12.5):
$\tau \approx 12.5 - 9.8 = \mathbf{+2.7}$ 万円
「人口 500 人差」では他の要因はほぼ同じはず → この差は市制施行の効果と解釈できる。 ただし 2 点だけの比較は不安定なので、 局所線形回帰で全体を使う。
モデル:$Y_i = \alpha + \tau D_i + \beta_1 (X_i - c) + \beta_2 D_i (X_i - c) + \varepsilon_i$
これは 4 つのパラメータ:
上のデータで OLS で回帰を回すと、 おおよそ:
$\hat{Y} = 10.0 + \underbrace{2.5}_{\tau}\cdot D + (-7.5 \times 10^{-5})\cdot(X - c) + ...$
結論:閾値での因果効果 $\hat{\tau} \approx +2.5$ 万円。 つまり、 「市制施行で 1 人当たり地方交付税が約 2.5 万円増える」と推定される。 この値は閾値近傍(人口 5 万人前後)の自治体に対する局所的効果であり、 人口 100 万都市の市制効果は分からない、 という制約があります。
RDD の最重要図表は「散布図 + 閾値の左右で別々のフィット線」。 これで「不連続性が本当にあるか」を視覚的に確認します。 ジャンプが目視で明らかなら結果は頑健、 微小なら推定が不安定。
import pandas as pd import numpy as np import matplotlib.pyplot as plt import statsmodels.api as sm # SSDSE-B を読み込み(直書きパス) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1) # 2023 年データに絞る df_2023 = df[df['年度'] == 2023].copy() # 強制変数 X:人口、 結果変数 Y:1人当たり地方交付税 df_2023['pop'] = df_2023['A1101'] # 総人口(仮コード) df_2023['tax_per_capita'] = df_2023['D1101'] / df_2023['A1101'] # 閾値の設定(仮想例):人口 50万人を境に「政令市」相当とみなす cutoff = 500000 df_2023['D'] = (df_2023['pop'] >= cutoff).astype(int) df_2023['X_centered'] = df_2023['pop'] - cutoff print(f"n = {len(df_2023)}, 処置群 = {df_2023['D'].sum()}")
# 帯域幅 h を設定(閾値の±300,000 人を採用、 教育用に固定) h = 300000 sample = df_2023[(df_2023['pop'] >= cutoff - h) & (df_2023['pop'] <= cutoff + h)].copy() # 相互作用項を作る sample['D_X'] = sample['D'] * sample['X_centered'] # 局所線形回帰モデル:Y = α + τD + β1(X-c) + β2 D(X-c) + ε X_mat = sm.add_constant(sample[['D', 'X_centered', 'D_X']]) y = sample['tax_per_capita'] model = sm.OLS(y, X_mat).fit(cov_type='HC1') # 不均一分散頑健な標準誤差 print(model.summary()) # 因果効果(τ)の推定値と信頼区間 tau = model.params['D'] ci = model.conf_int().loc['D'] print(f"τ = {tau:.3f} 95% CI: [{ci[0]:.3f}, {ci[1]:.3f}]")
fig, ax = plt.subplots(figsize=(10, 6)) # 散布図(閾値の左右で色分け) left = sample[sample['D'] == 0] right = sample[sample['D'] == 1] ax.scatter(left['pop'], left['tax_per_capita'], color='steelblue', label='町・村 (D=0)', s=60) ax.scatter(right['pop'], right['tax_per_capita'], color='crimson', label='市 (D=1)', s=60) # 閾値の左右で別々の線形フィット for sub, color in [(left, 'steelblue'), (right, 'crimson')]: m, b = np.polyfit(sub['pop'], sub['tax_per_capita'], 1) xs = np.linspace(sub['pop'].min(), sub['pop'].max(), 100) ax.plot(xs, m * xs + b, color=color, linewidth=2) # 閾値を縦線で示す ax.axvline(cutoff, color='black', linestyle='--', label=f'閾値 = {cutoff:,} 人') ax.set_xlabel('人口 (人)') ax.set_ylabel('1人当たり地方交付税 (円)') ax.set_title('RDD: 市制施行の財政効果(仮想シナリオ)') ax.legend() plt.tight_layout() plt.show()
受験者が「あと 1 点で合格」を意図して試験を解いたり、 役所が「あと数百人で市」と画策したりすると、 閾値直下/直上でサンプル数の人為的偏りが生じます。 これを検出するのが McCrary (2008) の密度検定:
# 閾値前後の人口ヒストグラムを描いて、 不自然な密度ジャンプがないか確認 fig, ax = plt.subplots(figsize=(10, 5)) ax.hist(sample['pop'], bins=30, edgecolor='black') ax.axvline(cutoff, color='red', linestyle='--', label='閾値') ax.set_title('McCrary 密度検定:閾値前後で X の密度に不自然なジャンプがないか') plt.show() # 専用パッケージ rddensity(要インストール)の例 # from rddensity import rddensity # result = rddensity(sample['pop'], c=cutoff) # print(result)
# 処置と関係なさそうな変数(例:高齢化率、 共変量)で同じRDDを回す # ジャンプが検出されないことが「識別仮定が成り立つ」傍証 for var in ['aging_rate', 'avg_income', 'unemployment']: y_placebo = sample[var] model_p = sm.OLS(y_placebo, X_mat).fit(cov_type='HC1') tau_p = model_p.params['D'] p_val = model_p.pvalues['D'] print(f"{var}: τ = {tau_p:.3f} (p={p_val:.3f})") # p > 0.05 で「ジャンプなし」なら識別仮定が支持される
# pip install rdrobust が必要 from rdrobust import rdrobust, rdplot, rdbwselect # 最適帯域幅の選択(CCT 法) bw = rdbwselect(y=sample['tax_per_capita'], x=sample['pop'], c=cutoff) print(bw) # RDD 推定(バイアス補正付き頑健信頼区間) result = rdrobust( y=sample['tax_per_capita'], x=sample['pop'], c=cutoff, p=1 # 局所線形(p=2 で局所2次) ) print(result) # 標準的なRDDプロット rdplot(y=sample['tax_per_capita'], x=sample['pop'], c=cutoff)
| 項目 | Sharp RDD | Fuzzy RDD |
|---|---|---|
| 処置の決まり方 | $X \ge c$ なら必ず $D = 1$、 そうでなければ必ず $D = 0$ | $X \ge c$ で処置確率が「ジャンプ」するが 0→1 とは限らない |
| 例 | 受験点数 60 点以上 = 必ず合格、 人口 5 万人以上 = 必ず市 | 奨学金の所得制限 = 制限以下でも申請しない人がいる、 制限超でも特例で受給する人がいる |
| 識別される量 | 閾値での平均処置効果 (ATE at c) | 閾値でのコンプライアー平均処置効果 (LATE for compliers) |
| 推定方法 | $Y$ を $X, D$ で局所線形回帰 | 2 段階最小二乗法(2SLS):$D$ を $\mathbf{1}\{X \ge c\}$ で操作変数推定 |
| τ の計算 | $\tau = \lim_{x \downarrow c} E[Y|X=x] - \lim_{x \uparrow c} E[Y|X=x]$ | $\tau = \dfrac{\text{Y のジャンプ}}{\text{処置確率のジャンプ}}$ |
Fuzzy RDD は操作変数法と同型で、 「閾値を超えたかどうか」を処置の操作変数として使います。 これにより部分コンプライアンス(処置を受けたい人だけが受ける)状況でも因果効果が識別できます。
RDD と因果推論手法群の関係を整理します。
【因果推論の Goal】
「X → Y の効果は何か?」
│
┌─────────────────┴─────────────────┐
▼ ▼
【実験的手法】 【観察データ手法】
・RCT │
┌──────────┼──────────┐
▼ ▼
【識別戦略あり】 【識別戦略なし】
│ │
┌───────┬───────┼───────┬──────────────┘
▼ ▼ ▼ ▼
【RDD】 【DiD】 【IV】 【マッチング】
│ │ │ │
│ │ │ └─ 傾向スコア
│ │ │
│ │ └─ 2SLS、 Fuzzy RDD
│ │
│ └─ パネルデータ、 二元固定効果
│
└─ Sharp RDD / Fuzzy RDD / RKD / Bunching
RDD は政策評価論文で最も信頼される識別戦略の 1 つです。 代表的な研究を題材別に整理します。
イスラエルの「マイモニデス・ルール」:学級規模が 40 人を超えると 2 クラスに分割される制度を利用。 39 人クラスと 41 人クラス(→ 1 クラス 21 人)を比べて、 学級規模縮小の学力効果を識別。 結論:小さい学級は学力テスト点数を改善(5 年生で約 0.25 SD)。 RDD の応用として有名な古典的研究。
米国下院議員選挙で、 「現職効果」を Sharp RDD で識別。 「得票率 50% 直上で当選 → 次回も当選しやすいか」を比較。 50.01% で当選した候補は次回の当選確率が大きくジャンプ。 因果効果は約 +9 ポイント。 「現職効果」が現実に存在することを RDD で明示した代表例。
米国で「21 歳の飲酒解禁」を Sharp RDD として利用。 21 歳の誕生日前後で死亡率がどうジャンプするか調査。 結論:21 歳誕生日直後の数日間で交通事故・アルコール関連死亡率が顕著にジャンプ。 法的飲酒年齢の効果を明示。
米国の労組結成投票で、 「過半数(50%)超で労組結成」というルールを Fuzzy RDD として利用。 結成 vs 不結成の前後で企業の業績・雇用者の賃金変化を比較。 結論:労組結成は企業の生存率や生産性に強い負の効果は見出せなかった、 という意外な発見。
ウルグアイの貧困世帯向け移転給付プログラム「PANES」。 所得テストスコアの閾値で給付が決まる制度を利用。 子どもの学校在籍率への影響を識別。 RDD で開発援助の効果を測定した代表例。
| 研究 | 強制変数 | 閾値 | 結果変数 | 主な結論 |
|---|---|---|---|---|
| Angrist & Lavy (1999) | 学級規模 | 40 人 | 学力テスト | 小クラスで +0.25 SD |
| Lee (2008) | 得票率 | 50% | 次回当選率 | 現職効果 +9 pt |
| Carpenter & Dobkin (2009) | 年齢 | 21 歳 | 死亡率 | 飲酒解禁直後にジャンプ |
| Black (1999) | 住所 | 学区境界 | 住宅価格 | 良い学区で +2.5% |
| Hahn et al. (1999) | 選挙得票 | 50% | 議席 | RDD 理論の原典 |
| Card et al. (2008) | 失業給付額 | 制限 | 再就職期間 | 給付増で就職遅延 |
| Pop-Eleches & Urquiola (2013) | 入試得点 | 合格点 | 大学進学 | 進学率に強い不連続 |
| 項目 | 確認内容 | 失敗時の影響 |
|---|---|---|
| 制度的閾値 | 処置が機械的に決まるルールが明文化されているか | 識別が成立しない |
| 連続性仮定 | 共変量・潜在結果が閾値で連続か | 因果効果が交絡 |
| McCrary 密度検定 | 強制変数の密度に不自然なジャンプがないか | 操作の疑い |
| 共変量プラセボ | 他の変数で閾値ジャンプが出ないか | 未観測交絡の疑い |
| 帯域幅の頑健性 | $h$ を変えて結果が安定か | 結果が局所的な偶然 |
| 多項式次数 | 低次(1〜2)に限定 | 境界の過剰適合 |
| RDD プロット | 視覚的にジャンプが明瞭か | 統計的有意でも実質効果なし |
| 外的妥当性 | 閾値近傍以外への外挿の議論 | 政策提言が過大解釈 |
De la Cuesta & Imai (2016) は、 政治学分野の RDD 研究 50 件以上をメタ分析。 「閾値での操作」「帯域幅依存」「多項式選択」の 3 大問題を体系的に検証し、 ベストプラクティスを提示。 結論:適切に分析されれば RDD は IV やマッチングより信頼性が高い識別戦略。