Mímisbrunnr知恵の泉

← 因果推論 一覧

🎓 レベル:標準 | 重要度:A(必須)

📎 前提:操作変数法と2SLS | 差分の差分と並行トレンド | 回帰不連続デザイン

要点(BLUF)


発想の転換:手法でなく「変動源」から考える

因果推論の各デザインは、結局「処置を、結果の交絡から切り離して動かす変動はどこにあるか」を問うている。

一覧:変動源と識別仮定

デザイン使う変動源主要な識別仮定効果の対象
RCT実験者のランダム割当無作為化=交換可能性ATE
回帰/傾向スコア・AIPW観測共変量での比較条件付き交換可能性(全交絡を観測)+正値性ATE / ATT
操作変数・2SLS外生的な揺さぶり Z関連性・除外制約・独立性(+単調性)LATE(コンプライア)
差分の差分群 × 時間の差並行トレンドATT
回帰不連続閾値前後の偶然閾値での連続性(操作なし)閾値での LATE
合成コントロール単一処置+ドナー干渉なし+凸包・良好な事前フィット処置ユニットへの効果

要は 「検証できる仮定」と「信じるしかない仮定」のどちらに賭けるか。RCTは無作為化を設計で保証できる唯一の手法。観察データの各デザインは、検証不能な仮定(全交絡観測・除外制約・並行トレンド・連続性)を理屈で支えるぶん脆い。

意思決定フロー

flowchart TD
    Start["因果効果を知りたい"] --> Q1{"処置をランダム割当できる?"}
    Q1 -->|"はい"| RCT["RCT(実験・A/Bテスト)"]
    Q1 -->|"いいえ(観察データ)"| Q2{"交絡をすべて観測できている?"}
    Q2 -->|"はい(強い無視可能性)"| ADJ["回帰/傾向スコア調整・AIPW"]
    Q2 -->|"いいえ(未観測交絡あり)"| Q3{"外生的な操作変数がある?"}
    Q3 -->|"はい(関連+除外)"| IV["操作変数法・2SLS"]
    Q3 -->|"いいえ"| Q4{"閾値で処置が決まる?"}
    Q4 -->|"はい"| RDD["回帰不連続デザイン"]
    Q4 -->|"いいえ"| Q5{"前後×群のパネルで並行トレンドが妥当?"}
    Q5 -->|"はい"| DID["差分の差分"]
    Q5 -->|"いいえ"| Q6{"処置は単一ユニット+良いドナー?"}
    Q6 -->|"はい"| SCM["合成コントロール法"]
    Q6 -->|"いいえ"| SENS["識別困難 → 感度分析で頑健性を測る"]

このフローは上ほど仮定が軽く信頼が高い。下りるほど検証不能な仮定が重くなる。複数のデザインが使えるなら、別々の仮定に立つ手法で同じ結論が出るか(三角測量)を確かめるのが最強だ。

コード:同じ効果を、観測できる変動源で取り分ける

同一のデータ生成過程(真の効果 β=2\beta=2、交絡 CC、操作変数 ZZ)に対し、何を観測できるかで勝つデザインが変わることを示す。(1) 交絡 CC を観測できれば回帰調整で当たる。(2) CC を観測できないと素朴回帰は偏る。(3) だが操作変数 ZZ があればIVで当たる。

import numpy as np
import statsmodels.api as sm

# === 同じ真の効果を、利用できる変動源に応じて違うデザインで取り出す ===
rng = np.random.default_rng(5)
n = 8000
beta_true = 2.0

C = rng.normal(0, 1, n)            # 交絡(観測できる場合とできない場合を比べる)
Z = rng.normal(0, 1, n)           # 操作変数(C と独立)
T = 0.8*Z + 1.0*C + rng.normal(0, 1, n)
Y = 1.0 + beta_true*T + 1.5*C + rng.normal(0, 1, n)

# (1) 交絡 C が観測できる → 回帰で調整(バックドアを閉じる)
adj = sm.OLS(Y, sm.add_constant(np.column_stack([T, C]))).fit().params[1]
# (2) C が観測できない → 素朴回帰は偏る
naive = sm.OLS(Y, sm.add_constant(T)).fit().params[1]
# (3) C は不明だが操作変数 Z がある → IV(2SLS)
T_hat = sm.OLS(T, sm.add_constant(Z)).fit().fittedvalues
iv = sm.OLS(Y, sm.add_constant(T_hat)).fit().params[1]

print(f"真の効果                        = {beta_true:.3f}")
print(f"(1) 交絡を観測→回帰で調整       = {adj:.3f}")
print(f"(2) 交絡を観測できず→素朴回帰   = {naive:.3f}")
print(f"(3) 交絡は不明だが操作変数→IV   = {iv:.3f}")

出力は次の通り。

真の効果                        = 2.000
(1) 交絡を観測→回帰で調整       = 2.012
(2) 交絡を観測できず→素朴回帰   = 2.568
(3) 交絡は不明だが操作変数→IV   = 1.951

交絡 CC観測できるなら回帰調整が2.012で真値を当てる。観測できないと素朴回帰は2.568へ偏る。しかし操作変数 ZZ があるなら、CC を一切観測せずともIVが1.951で回収する。手法の優劣は固定でなく、利用できる変動源で決まる。これがデザイン選択の本質だ。

仮定の直観:何が検証でき、何は信じるしかないか

検証不能な仮定に賭ける以上、結論は仮定とセットで提示し、仮定が崩れたらどれだけ結論がぶれるかを測る――それが第7章の感度分析だ。

⚠️ よくある誤解・落とし穴

関連ノート