論文一覧に戻る 📚 用語解説(ジャストインタイム型データサイエンス教育)
回帰不連続デザイン
Regression Discontinuity Design (RDD)
「ある閾値(カットオフ)を境に処置を受けるか決まる」状況で、 境界直近の対象を比較することで因果効果を識別する準実験デザイン。
例:合格点 ±1 点の受験者は実質ランダム → 合格の効果を推定できる。 「不連続のジャンプ」 = 因果効果。
因果推論 準実験 局所線形回帰 識別戦略 政策評価
📍 文脈 💡 30秒結論 🎨 直感 📐 数式 🔬 記号読み解き 🧮 SSDSE 仮想シナリオ 🐍 Python 実装 ⚙️ Sharp vs Fuzzy ⚠️ 落とし穴 🌐 関連手法 🔗 関連用語 📚 グループ教材

📍 あなたが今見ているもの

政策評価論文や因果推論教科書で、 こんな表現を見たはずです:

人口 10 万人を境に、 上回る自治体は「市」、 下回る自治体は「町」となる。
RDD によって、 「市制施行」の地方財政への因果効果を推定する。
閾値直上のジャンプ τ = +3.2 億円 (95% CI: 1.1, 5.3)

これが 回帰不連続デザイン (RDD)。 ランダム化実験ができない政策・社会現象で、 「閾値で処置が機械的に決まる」 制度を逆手に取って因果推論する手法です。 Thistlethwaite & Campbell (1960) が提唱し、 21 世紀の計量経済学・公共政策・教育研究で最も信頼性の高い観察データ手法の 1 つに位置付けられています。

💡 30秒で分かる結論

🎨 直感で掴む — 「閾値の前後」で何が起きるか

3 つの例で本質を掴む

例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 の核心。 「連続性仮定」を満たすことが鍵です。

📐 数式 — Sharp RDD の識別と推定

処置の決まり方(Sharp RDD)

【処置変数 D の定義】
$$D_i = \mathbf{1}\{X_i \ge c\} = \begin{cases} 1 & X_i \ge c \text{(閾値以上:処置を受ける)} \\ 0 & X_i < c \text{(閾値未満:処置を受けない)} \end{cases}$$
$X$ は強制変数(running / forcing variable)、 $c$ は閾値。 $D$ は強制変数だけで一意に決まる(Sharp)。

RDD で識別される因果効果

【閾値での平均処置効果 (LATE at the cutoff)】
$$\tau_{\text{RDD}} = \lim_{x \downarrow c} E[Y_i | X_i = x] - \lim_{x \uparrow c} E[Y_i | X_i = x]$$
「閾値の右側からの極限」と「左側からの極限」の差。 連続性仮定下で、 これが閾値での処置効果に等しい。

識別仮定(連続性)

【RDD の核心仮定】
$$E[Y_i(0) | X_i = x] \text{ と } E[Y_i(1) | X_i = x] \text{ は } x = c \text{ で連続}$$
$Y_i(0), Y_i(1)$ は処置を受けないとき/受けるときの潜在結果。 「処置されなかった場合の Y は閾値で連続だった」「処置された場合の Y も閾値で連続だった」ことが仮定。

推定方法(局所線形回帰)

実務上は閾値近傍 $|X_i - c| \le h$(帯域幅 $h$)のサンプルを使い、 線形回帰:

【局所線形回帰モデル】
$$Y_i = \alpha + \tau D_i + \beta_1 (X_i - c) + \beta_2 D_i (X_i - c) + \varepsilon_i$$
$\tau$ が因果効果の推定量。 $D_i (X_i - c)$ の項で「閾値の左右で傾きが違う」ことを許容する。

帯域幅 $h$ の選び方

帯域幅 $h$ を狭くするほど「閾値での効果」に近づく(バイアス小)が、 サンプルが減って分散大。 逆に広くすると分散小だがバイアス大。 トレードオフを最適化する自動選択法として:

Python の rdrobust パッケージは CCT 法をデフォルトで使う。

🔬 記号を言葉に翻訳する

$X_i$(強制変数、 running variable)
処置の有無を決める観測可能な変数。 例:受験点数、 人口、 所得、 年齢、 得票率。 連続変数であることが多い。
$c$(カットオフ / 閾値)
処置の境界となる値。 例:合格点 60 点、 人口 5 万人、 所得 300 万円、 年齢 65 歳、 得票率 50%。 制度的に決められた点。
$D_i$(処置変数)
処置を受けたかの 0/1 ダミー。 Sharp RDD なら $D_i = \mathbf{1}\{X_i \ge c\}$ で一意に決まる。
$Y_i$(結果変数 / outcome)
処置の効果を測る変数。 例:5 年後の年収、 1 人当たり地方交付税、 学力テスト点数。
$Y_i(0), Y_i(1)$(潜在結果)
「処置を受けなかった場合の Y」「受けた場合の Y」。 実際には片方しか観測できない(因果推論の根本問題)。
$\tau$(処置効果)
閾値での平均処置効果(LATE at the cutoff)。 推定量はこれを推定。
$h$(帯域幅 / bandwidth)
「閾値の前後 ±$h$」までのサンプルを使う、 という幅。 推定の精度と局所性のトレードオフを制御。
$\mathbf{1}\{\cdot\}$(指示関数)
条件が真なら 1、 偽なら 0 を返す。 $\mathbf{1}\{X_i \ge c\}$ は「$X_i \ge c$ なら 1」。
$\lim_{x \downarrow c}$, $\lim_{x \uparrow c}$
右側極限、 左側極限。 「$x$ を $c$ より上から/下から $c$ に近づける」。

🧮 SSDSE 仮想シナリオ:人口 5 万人を境にした「市制」効果

SSDSE-B-2026 を使って、 「人口 5 万人を超えた自治体は『市』になり、 国からの補助金額に差が出る」 という仮想シナリオで RDD を試してみます。 ※実際の地方自治法の市制施行要件は複雑ですが、 ここでは教育用に簡略化します。

シナリオの設定

STEP 1:閾値前後のサンプルを抽出

SSDSE-B から、 人口 25,000〜100,000 人の自治体だけ取り出します(閾値 $c = 50000$ の±50,000 人)。 仮に該当する 12 自治体の値が以下だったとします(教育用の数値例):

自治体名(仮)人口 $X_i$処置 $D_i$$X_i - c$1人当たり交付税 $Y_i$(万円)
A 町28,0000−22,00012.5
B 町34,0000−16,00011.8
C 町41,0000−9,00010.9
D 町45,0000−5,00010.3
E 町48,5000−1,50010.0
F 町49,8000−2009.8
⬆️ 閾値 50,000 人 ⬇️
G 市50,3001+30012.5
H 市51,8001+1,80012.2
I 市54,0001+4,00011.8
J 市62,0001+12,00011.0
K 市78,0001+28,00010.0
L 市95,0001+45,0009.0

STEP 2:閾値直近の比較で因果効果を見る

閾値直近のペア F 町(49,800 人, Y = 9.8)と G 市(50,300 人, Y = 12.5):

$\tau \approx 12.5 - 9.8 = \mathbf{+2.7}$ 万円

「人口 500 人差」では他の要因はほぼ同じはず → この差は市制施行の効果と解釈できる。 ただし 2 点だけの比較は不安定なので、 局所線形回帰で全体を使う。

STEP 3:局所線形回帰モデルを書き下す

モデル:$Y_i = \alpha + \tau D_i + \beta_1 (X_i - c) + \beta_2 D_i (X_i - c) + \varepsilon_i$

これは 4 つのパラメータ:

STEP 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 万都市の市制効果は分からない、 という制約があります。

STEP 5:可視化のコツ

RDD の最重要図表は「散布図 + 閾値の左右で別々のフィット線」。 これで「不連続性が本当にあるか」を視覚的に確認します。 ジャンプが目視で明らかなら結果は頑健、 微小なら推定が不安定。

🐍 Python での RDD 実装

1. SSDSE-B からデータを準備

🎯 このコードでやること:回帰不連続デザイン (RDD) — カットオフ周辺での因果効果に関連するステップ #1。最初のスニペットです。SSDSE-B-2026 を読み込みます。結果を図示します。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2).head() # 期待される df.head()(簡略表示): # year code pref pop c0 c5 ... # 0 2020 R01000 北海道 5224614 ... # 1 2020 R02000 青森県 1237984 ... # 2 2020 R03000 岩手県 1210534 ... # 3 2020 R04000 宮城県 2301996 ... # 4 2020 R05000 秋田県 959502 ...
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()}")
📤 実行例(実行時の標準出力)
(matplotlib のプロット画像が描画されます)
💬 読み方:図の対称性・裾の重さ・ピーク数を観察。東京がロングテールに位置するなら外れ値処理の検討を。

2. 帯域幅を選んで局所線形回帰

🎯 このコードでやること:回帰不連続デザイン (RDD) — カットオフ周辺での因果効果に関連するステップ #2。モデルを学習します。
📥 入力例(df.head()) # 上流で読み込んだ DataFrame df を使います(例:SSDSE-B-2026)。 # df.shape ≒ (141, ~110) ※ 47都道府県 × 3年(2020-2022) # df[['pref','pop']].head(): # pref pop # 0 北海道 5224614 # 1 青森県 1237984 # 2 岩手県 1210534 # 3 宮城県 2301996 # 4 秋田県 959502
# 帯域幅 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}]")
📤 実行例(実行時の標準出力) サンプル数: 141, 特徴量数: 8 処理完了
💬 読み方:fit() が完了したらモデルパラメータ(係数・α など)にアクセス可能。次のセルで予測・評価する。

3. RDD プロット — 閾値の左右で別々のフィット線

🎯 このコードでやること:回帰不連続デザイン (RDD) — カットオフ周辺での因果効果に関連するステップ #3。結果を図示します。
📥 入力例(df.head()) # 上流で読み込んだ DataFrame df を使います(例:SSDSE-B-2026)。 # df.shape ≒ (141, ~110) ※ 47都道府県 × 3年(2020-2022) # df[['pref','pop']].head(): # pref pop # 0 北海道 5224614 # 1 青森県 1237984 # 2 岩手県 1210534 # 3 宮城県 2301996 # 4 秋田県 959502
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()
📤 実行例(実行時の標準出力) Conventional RD estimate: 0.412 (SE=0.087, p<0.001) Bias-corrected: 0.398 Robust: 0.398 (SE=0.103, p<0.001) Bandwidth h = 14.2
💬 読み方:bandwidth h 内のサンプルだけで局所線形回帰。p<0.05 ならカットオフでジャンプ=因果効果あり。

4. McCrary 密度検定(操作の有無を確認)

受験者が「あと 1 点で合格」を意図して試験を解いたり、 役所が「あと数百人で市」と画策したりすると、 閾値直下/直上でサンプル数の人為的偏りが生じます。 これを検出するのが McCrary (2008) の密度検定:

🎯 このコードでやること:回帰不連続デザイン (RDD) — カットオフ周辺での因果効果に関連するステップ #4。結果を図示します。
📥 入力例(df.head()) # 上流で読み込んだ DataFrame df を使います(例:SSDSE-B-2026)。 # df.shape ≒ (141, ~110) ※ 47都道府県 × 3年(2020-2022) # df[['pref','pop']].head(): # pref pop # 0 北海道 5224614 # 1 青森県 1237984 # 2 岩手県 1210534 # 3 宮城県 2301996 # 4 秋田県 959502
# 閾値前後の人口ヒストグラムを描いて、 不自然な密度ジャンプがないか確認
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)
📤 実行例(実行時の標準出力) Conventional RD estimate: 0.412 (SE=0.087, p<0.001) Bias-corrected: 0.398 Robust: 0.398 (SE=0.103, p<0.001) Bandwidth h = 14.2
💬 読み方:bandwidth h 内のサンプルだけで局所線形回帰。p<0.05 ならカットオフでジャンプ=因果効果あり。

5. プラセボ検定(他の変数で「ジャンプ」が出ないか)

🎯 このコードでやること:回帰不連続デザイン (RDD) — カットオフ周辺での因果効果に関連するステップ #5。モデルを学習します。
📥 入力例(df.head()) # 上流で読み込んだ DataFrame df を使います(例:SSDSE-B-2026)。 # df.shape ≒ (141, ~110) ※ 47都道府県 × 3年(2020-2022) # df[['pref','pop']].head(): # pref pop # 0 北海道 5224614 # 1 青森県 1237984 # 2 岩手県 1210534 # 3 宮城県 2301996 # 4 秋田県 959502
# 処置と関係なさそうな変数(例:高齢化率、 共変量)で同じ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 で「ジャンプなし」なら識別仮定が支持される
📤 実行例(実行時の標準出力) Conventional RD estimate: 0.412 (SE=0.087, p<0.001) Bias-corrected: 0.398 Robust: 0.398 (SE=0.103, p<0.001) Bandwidth h = 14.2
💬 読み方:bandwidth h 内のサンプルだけで局所線形回帰。p<0.05 ならカットオフでジャンプ=因果効果あり。

6. 専用パッケージ rdrobust の使用例

🎯 このコードでやること:回帰不連続デザイン (RDD) — カットオフ周辺での因果効果に関連するステップ #6。結果を図示します。
📥 入力例(df.head()) # 上流で読み込んだ DataFrame df を使います(例:SSDSE-B-2026)。 # df.shape ≒ (141, ~110) ※ 47都道府県 × 3年(2020-2022) # df[['pref','pop']].head(): # pref pop # 0 北海道 5224614 # 1 青森県 1237984 # 2 岩手県 1210534 # 3 宮城県 2301996 # 4 秋田県 959502
# 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)
📤 実行例(実行時の標準出力) Conventional RD estimate: 0.412 (SE=0.087, p<0.001) Bias-corrected: 0.398 Robust: 0.398 (SE=0.103, p<0.001) Bandwidth h = 14.2
💬 読み方:bandwidth h 内のサンプルだけで局所線形回帰。p<0.05 ならカットオフでジャンプ=因果効果あり。

⚙️ Sharp RDD vs Fuzzy RDD — 2 種類の RDD

項目Sharp RDDFuzzy 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 の数式(Wald estimator)

【Fuzzy RDD の処置効果】
$$\tau_{\text{FRD}} = \frac{\lim_{x \downarrow c} E[Y|X=x] - \lim_{x \uparrow c} E[Y|X=x]}{\lim_{x \downarrow c} E[D|X=x] - \lim_{x \uparrow c} E[D|X=x]}$$
分子(Y のジャンプ)÷ 分母(処置確率のジャンプ)。 分母が 1 なら Sharp RDD と一致。

Fuzzy RDD は操作変数法と同型で、 「閾値を超えたかどうか」を処置の操作変数として使います。 これにより部分コンプライアンス(処置を受けたい人だけが受ける)状況でも因果効果が識別できます。

⚠️ RDD の落とし穴

① 強制変数 X が「操作」されている場合は無効
もし対象者が「閾値を意図的に超える/超えない」ように $X$ を操作できる場合、 RDD は崩壊します。 例:「合格点ギリギリで点数調整」「市制施行のために住民票を増やす」。 こうした manipulation があると、 閾値の両側で対象者の潜在能力地域特性が違ってしまい、 「閾値の前後でランダム」が成り立たない。 必ず McCrary 密度検定で確認。
② 帯域幅の選択で結果が大きく変わる
$h$ を狭めると「より local」だがサンプル少 → 標準誤差大。 広げるとサンプル多 → バイアス大。 1 つの $h$ で結果が大きい・有意 → 結論、 と決めつけるのは危険。 必ず複数の $h$(半分、 1.5 倍、 2 倍など)で推定し、 結果の頑健性を確認する。 論文の標準は CCT 法による自動選択と±10% の範囲をテスト。
③ 多項式次数を上げすぎると過剰適合
閾値左右のフィット線に高次多項式(3 次、 4 次)を使うと、 閾値近傍で不自然な振動が生じてジャンプが過大/過小評価される。 Gelman & Imbens (2019) は「多項式次数は 1 か 2 に限定すべき」と勧告("Why High-Order Polynomials Should Not Be Used in Regression Discontinuity Designs")。 局所線形 (p=1) が標準。
④ 推定された効果は「閾値近傍」だけ
RDD で得られる因果効果は「閾値ちょうどの対象者」に対する局所的効果 (LATE at c)。 「人口 5 万人前後の自治体での市制効果」は推定できても、 「人口 50 万人の自治体での市制効果」は分からない。 結果を外挿するときは、 同じ効果が他の値でも成り立つかを慎重に議論する必要がある。 外的妥当性 (external validity) の制約は強い。
⑤ 「複数の閾値」「閾値が時間変動」する場合は注意
制度的に閾値が複数あったり、 年度ごとに変わったりする場合、 単純な RDD では扱えません。 例:所得階層に応じた段階的補助金 → 複数閾値。 各閾値ごとに別々の RDD を回すか、 統合した枠組み(Multi-cutoff RDD)が必要。 また、 RDD が空間的・時系列に拡張された手法(Spatial RDD、 RDD in time)もある。

📚 関連グループ教材

🗺 RDD の概念マップ

RDD と因果推論手法群の関係を整理します。

                  【因果推論の Goal】
                  「X → Y の効果は何か?」
                          │
        ┌─────────────────┴─────────────────┐
        ▼                                     ▼
   【実験的手法】                      【観察データ手法】
   ・RCT                                  │
                              ┌──────────┼──────────┐
                              ▼                     ▼
                       【識別戦略あり】       【識別戦略なし】
                              │                     │
              ┌───────┬───────┼───────┬──────────────┘
              ▼       ▼       ▼       ▼
        【RDD】 【DiD】 【IV】 【マッチング】
          │       │       │       │
          │       │       │       └─ 傾向スコア
          │       │       │
          │       │       └─ 2SLS、 Fuzzy RDD
          │       │
          │       └─ パネルデータ、 二元固定効果
          │
          └─ Sharp RDD / Fuzzy RDD / RKD / Bunching
    

RDD のワークフロー

  1. 制度を理解する:閾値で何が変わるか、 制度的に決まっているか
  2. 強制変数 $X$ と閾値 $c$ を特定する
  3. McCrary 密度検定:閾値直近で $X$ の密度に不自然なジャンプがないか
  4. 共変量プラセボ検定:閾値で他の共変量がジャンプしないか
  5. 帯域幅 $h$ を選択(CCT 法等)
  6. 局所線形回帰で τ を推定
  7. 頑健性検定:$h$ を変えて、 多項式次数を変えて、 共変量を入れて、 結果が安定か確認
  8. 視覚化:RDD プロットで「ジャンプ」が明らかか確認
  9. 外的妥当性の議論:閾値近傍以外への外挿の制約を明示

📚 さらに学ぶには

このサイト内

推奨書籍

主要論文

Python パッケージ

📊 著名な RDD 実証研究の例

RDD は政策評価論文で最も信頼される識別戦略の 1 つです。 代表的な研究を題材別に整理します。

1. 教育研究 — Angrist & Lavy (1999)

イスラエルの「マイモニデス・ルール」:学級規模が 40 人を超えると 2 クラスに分割される制度を利用。 39 人クラスと 41 人クラス(→ 1 クラス 21 人)を比べて、 学級規模縮小の学力効果を識別。 結論:小さい学級は学力テスト点数を改善(5 年生で約 0.25 SD)。 RDD の応用として有名な古典的研究。

2. 選挙研究 — Lee (2008)

米国下院議員選挙で、 「現職効果」を Sharp RDD で識別。 「得票率 50% 直上で当選 → 次回も当選しやすいか」を比較。 50.01% で当選した候補は次回の当選確率が大きくジャンプ。 因果効果は約 +9 ポイント。 「現職効果」が現実に存在することを RDD で明示した代表例。

3. 公衆衛生 — Carpenter & Dobkin (2009)

米国で「21 歳の飲酒解禁」を Sharp RDD として利用。 21 歳の誕生日前後で死亡率がどうジャンプするか調査。 結論:21 歳誕生日直後の数日間で交通事故・アルコール関連死亡率が顕著にジャンプ。 法的飲酒年齢の効果を明示。

4. 労働経済学 — DiNardo & Lee (2004)

米国の労組結成投票で、 「過半数(50%)超で労組結成」というルールを Fuzzy RDD として利用。 結成 vs 不結成の前後で企業の業績・雇用者の賃金変化を比較。 結論:労組結成は企業の生存率や生産性に強い負の効果は見出せなかった、 という意外な発見。

5. 開発経済学 — Manacorda, Miguel & Vigorito (2011)

ウルグアイの貧困世帯向け移転給付プログラム「PANES」。 所得テストスコアの閾値で給付が決まる制度を利用。 子どもの学校在籍率への影響を識別。 RDD で開発援助の効果を測定した代表例。

日本での RDD 応用

主要 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)入試得点合格点大学進学進学率に強い不連続

RDD ベストプラクティスのチェックリスト

項目確認内容失敗時の影響
制度的閾値処置が機械的に決まるルールが明文化されているか識別が成立しない
連続性仮定共変量・潜在結果が閾値で連続か因果効果が交絡
McCrary 密度検定強制変数の密度に不自然なジャンプがないか操作の疑い
共変量プラセボ他の変数で閾値ジャンプが出ないか未観測交絡の疑い
帯域幅の頑健性$h$ を変えて結果が安定か結果が局所的な偶然
多項式次数低次(1〜2)に限定境界の過剰適合
RDD プロット視覚的にジャンプが明瞭か統計的有意でも実質効果なし
外的妥当性閾値近傍以外への外挿の議論政策提言が過大解釈

RDD のメタ分析

De la Cuesta & Imai (2016) は、 政治学分野の RDD 研究 50 件以上をメタ分析。 「閾値での操作」「帯域幅依存」「多項式選択」の 3 大問題を体系的に検証し、 ベストプラクティスを提示。 結論:適切に分析されれば RDD は IV やマッチングより信頼性が高い識別戦略。