論文一覧に戻る 📚 用語解説(ジャストインタイム型データサイエンス教育)
差分の差分法(DiD)
Difference-in-Differences (DiD)
処置群と対照群の前後差を比較する準実験的因果推論手法。共通トレンド仮定が鍵。
因果推論DiDDiD差分の差分DID

🔖 キーワード索引 — 完全強化版

🔖 キーワード索引 — 完全強化版

「差の差分析(DID)」を理解するうえで必要なキーワードを 10 件以上提示します。 各チップから対応セクションへ移動できます。

30 秒結論 文脈 直感 数式 記号読み解き 実値計算 Python 実装 落とし穴 関連手法 関連用語 グループ教材 概念マップ

💡 30秒で分かる結論

🍰 まずはやさしく

2つのグループの変化を比べる方法です。

ある対策の効果を正しく知るために使います。

スマホの利用制限で成績が変わったか調べます。

この章では結論を短くまとめました。

📖 包括的解説 — この概念を完全マスター

📍 学習の3ステップ

  1. 定義を理解する:この概念は何か? 数式や条件を確認
  2. 具体例を見る:実データ(SSDSE 等)で計算してみる
  3. 応用する:自分のデータに適用、 結果を解釈

💡 30 秒で分かる結論 — 完全強化版

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

🍰 まずはやさしく

データ分析で使う特別な道具のようなものです。

原因と結果の関係をはっきりさせるために使います。

都市のルール変更で生活がどう変わったか調べます。

この用語がどこで使われるかを説明します。

論文中に 「差分の差分法(DiD)」として登場する用語。

差分の差分法(DiD) とは:処置群と対照群の前後差を比較する準実験的因果推論手法。共通トレンド仮定が鍵。

📍 文脈ボックス — あなたが今見ているもの(完全強化版)

このセクションは「差の差分析(DID)」を扱う 用語ページ です。 統計データ分析コンペティション(2026)の再現教材における中核用語のひとつで、政令指定都市と非政令指定都市の比較(前後差の差) という観点で SSDSE-B-2026(47 都道府県 × 複数年 × 100 超列)に紐づけられます。

位置づけ:相関線形回帰仮説検定 といった基礎用語群と並列であり、応用としては 内生性IVDIDクラスタリング 等へ繋がります。

🎨 直感で掴む — 完全強化版

🍰 まずはやさしく

データを読み解くための眼鏡のようなものです。

隠れた変化を見つけ出すために使います。

部活の練習法を変えて、上達したか比べます。

直感的にイメージして理解していきましょう。

差の差分析(DID) を一言でいえば「政令指定都市と非政令指定都市の比較(前後差の差)」。 47 都道府県という小さな母集団でも、 SSDSE-B-2026 の A1101 列に注目すると、 大都市圏と地方の差・人口規模に伴う相対比較など、 様々なパターンが見えてきます。

比喩でいうと、 差の差分析(DID) はデータ分析の「眼鏡」のようなもの。 同じデータでも眼鏡を変えれば、 平均(中心)・分散(ばらつき)・相関(連動)・因果(影響)と、 異なる情報が浮かび上がります。 SSDSE-B-2026 を題材に、 この眼鏡をかけてみるのが本ページの狙いです。

🎨 概念図で押さえる(DiD の可視化)

差分の差分法(DiD)は「処置群と対照群の前後変化の差」で因果効果を推定する。 時系列の平行トレンド・処置効果のジャンプ・パネルデータ構造の 3 枚で、 DiD の幾何学的本質を把握する。

DiD の基本図:平行トレンドと処置効果
DiD の中核図。 処置群と対照群の処置前トレンドが平行と仮定し、 処置後のギャップが因果効果を表す。
時系列の基本構造(DiD の入力データ)
DiD は時系列パネルデータが前提。 各群の長期トレンドを観察してから処置効果を識別する。
パネルデータ構造(DiD のデータフォーマット)
パネルデータ(同一個体を時系列で追跡)が DiD の前提構造。 fixed effects と組み合わせると個体異質性を制御できる。

→ DiD 図で「2 群 × 2 期間」の本質、 時系列図で「トレンドの観察」、 パネル図で「データ構造」を整理。 平行トレンド仮定の検証がカギ。

✅ 理解度チェック

  1. 差分の差分法(DiD)が成立する最重要の仮定は何か?
  2. DiD と RCT(無作為化比較試験)の最大の違いは?
  3. 処置群と対照群の処置前トレンドが平行でない場合の対処法は?
  4. DiD を pandas で実装する最も基本的な手順を 3 ステップで答えよ。
  5. 「カードとクルーガーの最低賃金研究」が DiD の代表例とされる理由は?

→ すべて即答できれば、 DiD を政策評価・経営判断で適切に使い分けられる基礎力は十分。

📐 数式または定義 — 完全強化版

🍰 まずはやさしく

計算式で効果を導き出す方法です。

正確な数字で影響を測るために使います。

買い物でのポイント還元で支出が変わったか調べます。

ここからは具体的な数式について読みます。

差の差分析(DID) の代表的な定義式は次のとおりです。

$$ \hat{\tau}_{DID} = (\bar{Y}_{T,\text{post}} - \bar{Y}_{T,\text{pre}}) - (\bar{Y}_{C,\text{post}} - \bar{Y}_{C,\text{pre}}) $$

ここで使われる記号や演算の意味は次節で言葉に翻訳します。

🔬 数式を言葉で読み解く — 完全強化版

上の DID 定義式の各記号を、日本語の意味に変換します。

回帰で書くと Y = β₀ + β₁·treated + β₂·post + β₃·(treated×post) + ε の交差項係数 β₃ が τDID に対応します。

🧮 SSDSE-B-2026 を使った DID の実例 — 高齢化率の疑似 DID

SSDSE-B-2026 は 47 都道府県 × 12 年(2012〜2023)× 100 超列のパネルデータで、 DID の格好の練習台です。 実在の政策評価ではなく 手法デモ(疑似 DID)として、 「大都市圏(東京都・大阪府・愛知県)を仮の処置群、 残り 44 県を対照群」と見立て、 2018 年を境に 高齢化率(65 歳以上人口比率 = A1303 ÷ A1101 × 100)の推移を比較します。 以下の数値はすべて SSDSE-B-2026 の実測値から算出したものです。

① セットアップ(データ読込・処置/時期ダミー・結果変数)

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) A1303(65歳以上人口) 北海道 5,092,000 1,681,000 東京都 14,086,000 3,205,000 沖縄県 1,468,000 350,000 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import pandas as pd

# SSDSE-B-2026(1 行目=列コード, 2 行目=日本語名)を読み込む
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='cp932')
df = df.rename(columns={'SSDSE-B-2026': 'year'})   # 先頭列=年度

# 結果変数:高齢化率(65歳以上人口 A1303 ÷ 総人口 A1101 × 100, %)
df['aging'] = df['A1303'] / df['A1101'] * 100

# 疑似処置:大都市圏 3 都府県を処置群、 2018 年以降を処置後とみなす
treat = ['東京都', '大阪府', '愛知県']
df['treated'] = df['Prefecture'].isin(treat).astype(int)
df['post'] = (df['year'] >= 2018).astype(int)
df['treat_post'] = df['treated'] * df['post']
print(df[['year', 'Prefecture', 'aging', 'treated', 'post']].head())
📤 実行例(実測) year Prefecture aging treated post 0 2023 北海道 33.012569 0 1 1 2022 北海道 32.801556 0 1 2 2021 北海道 32.529423 0 1 3 2020 北海道 31.849683 0 1 4 2019 北海道 31.812132 0 1

② 2×2 集計と手計算 DID

処置群と対照群の、 2018 年(処置前)と 2023 年(処置後)の高齢化率の実測平均は次のとおりです。

 2018(前)2023(後)前後差
処置群(大都市圏 3 都府県平均)25.0725.38+0.31
対照群(他 44 県平均)30.3532.01+1.66
DID = (処置群の前後差) − (対照群の前後差) = (+0.31) − (+1.66) = −1.36 ポイント (対照群と比べ、 処置群の高齢化率は 5 年間で 1.36 ポイントぶん緩やかだった、 という差の差)

③ DID 回帰(交差項・固定効果・クラスタ頑健 SE)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import statsmodels.formula.api as smf

# ②と同じ 2 時点(2018=前, 2023=後)に絞り、 post を「2023 年ダミー」に定義し直す
d2 = df[df['year'].isin([2018, 2023])].copy()
d2['post'] = (d2['year'] == 2023).astype(int)
d2['treat_post'] = d2['treated'] * d2['post']

# 高齢化率 ~ 処置 + 時期 + 交差項(treat_post の係数が DID 推定値)
m = smf.ols('aging ~ treated + post + treat_post', data=d2).fit()
print(round(m.params['treat_post'], 2))   # -1.36(2×2 の手計算と一致)

# 県・年の固定効果を入れ、 県単位のクラスタ頑健 SE で再推定
m2 = smf.ols('aging ~ treat_post + C(Prefecture) + C(year)', data=d2) \
        .fit(cov_type='cluster', cov_kwds={'groups': d2['Prefecture']})
print(round(m2.params['treat_post'], 4), round(m2.bse['treat_post'], 4))  # -1.3561 0.3841
📤 実行例(実測) -1.36 -1.3561 0.3841

②と同じ 2 時点(2018・2023)に絞って回帰すると、 交差項 treat_post の係数は −1.3561(≒ −1.36)となり、 ②の手計算と厳密に一致します(2×2 DID と飽和回帰の代数的同値性)。 県・年の固定効果を入れても係数は −1.3561 のままで、 県単位のクラスタ頑健標準誤差は 0.3841。 パネルでは誤差が県内で時系列相関するため、 県単位のクラスタ頑健標準誤差で有意性を評価するのが定石です。 なお、 ①で作った 12 年分のパネル全体(post=2018 年以降)に同じ回帰を当てると係数は −1.76 になりますが、 これは「処置後 6 年間の平均差」という別の量を推定しているためで、 ②の 2×2 手計算と突き合わせる際は 2 時点に絞る必要があります。

④ 平行トレンドの確認(イベントスタディの考え方)

1
2
3
4
5
6
7
8
# 年ごとの群平均で「処置前トレンドが平行か」を目視確認する
trend = df.pivot_table(index='treated', columns='year',
                       values='aging', aggfunc='mean').round(2)
print(trend[[2012, 2015, 2018, 2021, 2023]])
# 処置群(1): 2012=22.12 → 2018=25.07(処置前 +2.95)
# 対照群(0): 2012=25.86 → 2018=30.35(処置前 +4.49)
# → 処置前から傾きが違う = 平行トレンド仮定は疑わしい。
#   イベントスタディ(処置前ダミーの係数が 0 近傍か)で厳密に検証する。
📤 実行例(実測) year 2012 2015 2018 2021 2023 treated 0 25.86 28.28 30.35 31.51 32.01 1 22.12 23.85 25.07 25.37 25.38

💬 解釈と注意:DID は −1.36 ポイントですが、 処置前(2012→2018)から両群の傾きが違う(対照群のほうが速く高齢化)ため、 平行トレンド仮定が成り立っていません。 したがってこの −1.36 を「政策効果」と断定はできず、 むしろ本例は平行トレンド検証の重要性を示す教材です。 これは実在の政策ではない疑似 DID であり、 実データで DID を行うときは必ずプレトレンド検定・イベントスタディをセットで実施してください。

🎮 触って理解する — 2×2 表と平行トレンドを動かす

DiD の心臓部は 2×2 表(処置群/対照群 × 処置前/処置後 の 4 つの平均)です。 下のスライダー(または右のグラフ上の丸い点を直接ドラッグ)で 4 つの値と さらに前の基準時点 を動かすと、 DID =(処置群の変化)−(対照群の変化) がリアルタイムで再計算され、 反実仮想(対照群のトレンドを処置群に当てはめた破線)と実測の縦の差=処置効果が可視化されます。 初期値は本ページ上の SSDSE-B-2026 実測値(高齢化率, %)です。

群 \ 時点 2012
(基準)
2018
(処置前)
2023
(処置後)
処置群
22.12
25.07
25.38
対照群
25.86
30.35
32.01
処置群の変化(2018→2023): / 対照群の変化:
DID =(処置群の変化)−(対照群の変化)= ポイント
反実仮想の 2023 年値(=処置群 2018 + 対照群の変化): / 処置効果=実測−反実仮想=
プレトレンド差(2012→2018 の傾きの差 = 処置群 − 対照群)=

💡 スライダーは 0.01 刻み。 グラフ上の丸い点を直接ドラッグ(スマホはタップして上下スワイプ)しても値が変わります。 青の破線は「もし処置群が対照群と同じトレンドで推移したら」を表し、 青の実線(実測)との縦の差(緑)が処置効果=DID です。 「プレトレンドを平行にする」を押すと、 水準差を保ったまま 2012→2018 の傾きだけを揃えられます。 DID の値は変わらないのに判定が「信頼できる」に変わることを確かめてください。

🧠 直感:共通のトレンドを差し引いて「効果だけ」を取り出す

処置群の前後差(初期値 +0.31)は「時間による自然な変化 + 政策効果」が混ざったもの。 このうち「時間による自然な変化」を、 政策の影響を受けていない対照群の前後差(+1.66)で代理し、 引き算で消去する。 残った −1.35 が処置効果の推定値です。 自然実験で得た擬似的な処置群・対照群に対し、 この「差の差」で反実仮想を近似するのが DiD の核心です。

⚠️ よくある落とし穴:平行トレンド仮定と処置前の差

🚀 発展:イベントスタディ・二方向固定効果・合成統制法

🐍 実装バリエーション — statsmodels / linearmodels / DiD パッケージ

(A) statsmodels OLS — シンプルな2x2 DID

🎯 解説: DID を回帰で推定するには「処置ダミー × 時期ダミー」の交差項の係数を見る。 統計検定(t 検定)で効果の有意性も確認できる。
1
2
3
4
5
import statsmodels.formula.api as smf
# 結果変数は 'y' ではなく、このページで作った 'aging'(高齢化率)。
# 交差項は treated:post と書けば、その場で作ってくれる
m = smf.ols('aging ~ treated + post + treated:post', data=df).fit()
print(round(m.params['treated:post'], 4))  # DID 推定値
📤 実行例(実測) -1.7639

(B) linearmodels PanelOLS — 双方向固定効果が簡単

🎯 解説: linearmodels の PanelOLS なら、 都道府県固定効果(EntityEffects)と年固定効果(TimeEffects)を式に書くだけで双方向固定効果 DID が組める。 被説明変数はこのページで作った aging(高齢化率)、 処置ダミーは treat_post(treated × post)。 SE は県クラスタで頑健化する。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from linearmodels.panel import PanelOLS
# 被説明変数はこのページで作った 'aging'(高齢化率)。df には
# year / Prefecture / aging / treated / post / treat_post が入っている
df_p = df.set_index(['Prefecture', 'year'])
m = PanelOLS.from_formula(
    'aging ~ 1 + treat_post + EntityEffects + TimeEffects',
    data=df_p).fit(cov_type='clustered', cluster_entity=True)
print(m.params.round(4))
print('p 値:', round(m.pvalues['treat_post'], 4))
# 都道府県固定効果・年固定効果とクラスタ頑健 SE を一行で
📤 実行例: Intercept 29.2960 treat_post -1.7639 Name: parameter, dtype: float64 p 値: 0.0001
💬 読み方: treat_post = −1.7639 は、 (B) の smf.ols で交差項を書いた推定値と小数第 4 位まで一致する。 双方向固定効果を入れても DID 推定値は変わらず、 p = 0.0001 で有意。

(C) DiD (Callaway & Sant'Anna) — 時差導入処置

🎯 解説: DID(差の差分析)は政策効果を測る手法。 SSDSE-B-2026 を 2 時点で見立て、 「処置群(政策実施県)と対照群の差」の「処置前後の差」を比較する。 トレンド共通の仮定が成立する場合のみ妥当。
1
2
3
4
5
6
# pip install differences
from differences import ATTgt
att = ATTgt(data=df, cohort_name='treat_year', strata_name=None,
            base_period='varying', anticipation=0).fit(formula='y ~ 1')
print(att.aggregate('simple'))
# 集約 ATT と動的 ATT を頑健に推定

(D) 合成統制法(SyntheticControlMethods)

🎯 解説: DID を回帰で推定するには「処置ダミー × 時期ダミー」の交差項の係数を見る。 統計検定(t 検定)で効果の有意性も確認できる。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import pandas as pd

# ── Synth に渡すパネルを用意する(都道府県 × 年 の高齢化率)──
_d = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df_pivot = pd.DataFrame({
    'Prefecture': _d['Prefecture'],
    'year': _d['SSDSE-B-2026'],
    'aging': _d['A1303'] / _d['A1101'] * 100,
}).sort_values(['Prefecture', 'year']).reset_index(drop=True)

from SyntheticControlMethods import Synth
scm = Synth(df_pivot, 'aging', 'Prefecture', 'year', 2015, '東京都', n_optim=10).fit()
scm.plot(['original', 'pointwise', 'cumulative'])
# 「合成東京都」を構築して、 実際の東京都との差で処置効果を推定

(E) scikit-learn の DoubleML(DID)

🎯 解説: 共通トレンド仮定を視覚的に確認する。 処置前の期間で処置群と対照群が並行に動いていれば、 仮定を支持。 並行でなければ DID の前提が崩れる。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import numpy as np
import pandas as pd
from doubleml import DoubleMLData

# ── DoubleML に渡すデータを用意する ──
_d = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
_aging = _d['A1303'] / _d['A1101'] * 100
_raw = pd.DataFrame({
    'y': _d['L3221'].astype(float),                        # 消費支出
    'treat': (_d['SSDSE-B-2026'] >= 2016).astype(int),     # 2016 年以降を処置後
    'x1': np.log(_d['A1101'].astype(float)),               # 総人口の対数
    'x2': _aging,                                          # 高齢化率
})
data = DoubleMLData(_raw, y_col='y', d_cols='treat', x_cols=['x1', 'x2'])

from doubleml import DoubleMLDID
from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier
dml_did = DoubleMLDID(data, y='y', d='treat', x_cols=['x1', 'x2'],
                      ml_g=RandomForestRegressor(), ml_m=RandomForestClassifier())
dml_did.fit()
print(dml_did.summary)  # 機械学習で nuisance を推定する高度版 DID

⚠️ 追加の落とし穴 — DID の実務

❌ 平行トレンドの検証を省略
DID の核心的仮定は「処置前の処置群と統制群が平行なトレンド」。 これを検証せずに DID を実行するのは、 ガソリンを入れずに車を走らせるようなもの。 (i) 処置前期間の年次平均をプロット、 (ii) リード項(処置前の偽処置)が有意でないかチェック、 (iii) イベントスタディで処置前係数が 0 近傍か確認。 平行が崩れていれば、 合成統制法、 propensity score matching、 IV など別手法へ。
❌ 時差導入処置で 2WFE を使う
Goodman-Bacon (2021)・Callaway-Sant'Anna (2021) が示したように、 処置時点が群ごとに違う(staggered adoption)場合、 標準的な双方向固定効果 (TWFE) DID は有害な比較(forbidden comparison)を含むため、 真の ATT を過小または逆符号で推定する。 対策:CS法、 de Chaisemartin-d'Haultfoeuille法、 Sun-Abraham法など現代的 staggered DID 手法を使う。 2020年代後半の必須知識。
❌ 標準誤差をクラスタリングしない
パネルデータでは個体内の誤差が時系列的に相関する。 通常の SE は過小評価される。 Bertrand-Duflo-Mullainathan (2004) 以降、 クラスター頑健 SE(個体レベルでクラスタリング)が必須。 statsmodels では fit(cov_type='cluster', cov_kwds={'groups': prefecture})。 47県のように少クラスター時はワイルドブートストラップ (wild cluster bootstrap) も検討。
❌ 処置の同時発生イベントに無頓着
処置(政策)の導入と同時期に別のショック(経済危機、 自然災害、 別の政策)があると、 DID 推定値はこの混合効果を含む。 処置効果と区別できない。 対策:(i) 別ショックの空間・時間広がりを調査、 (ii) 別ショックを別変数として制御、 (iii) 影響を受けない統制群の選定、 (iv) サンプル期間を分割して頑健性チェック。 同時イベントの存在を「研究の限界」として明示する誠実さも重要。
❌ 処置効果の異質性を無視
DID は通常「平均処置効果」を推定するが、 効果は群によって違う(若年層と高齢層、 都市と地方)可能性が高い。 (i) サブグループ別 DID、 (ii) 交互作用項を入れる、 (iii) Causal Forest、 DR-Learner などの異質処置効果推定。 政策含意の観点では「誰に効くか」が「効くか」より重要なことが多い。 機械学習との融合が現代的な発展方向。
❌ スピルオーバー効果を考慮しない
SUTVA(処置の安定単位値仮定):「処置群への処置が統制群に影響しない」。 実際は隣接県、 経済交流、 情報伝播でスピルオーバーが起きる。 例:県境地域、 通勤圏、 サプライチェーン。 対策:(i) スピルオーバー対象を分析対象から除外、 (ii) 距離・隣接ダミーで効果を測定、 (iii) 空間計量経済学的手法。 SUTVA違反は推定値を歪める。
❌ 予期的効果(anticipation)を見落とす
政策発表から実施まで時間がある場合、 処置群は政策発表後に行動を変える可能性がある。 これは事前のトレンド崩壊として現れ、 平行トレンド仮定を破る。 対策:(i) 発表時点を別の処置時点として扱う、 (ii) アンチサイペーション期間を分析から除外、 (iii) イベントスタディで予期効果の有無を視覚化。 政策評価では特に注意すべき問題。

⚠️ 落とし穴 — 完全強化版

差の差分析(DID) を実務で扱う際に踏みやすい落とし穴を 5 件挙げます。

🗺️ 概念マップ — 体系の中での位置

🗺️ 概念マップ — 3つの視点で体系を理解する

差分の差分法(DiD) がデータサイエンスの体系の中でどこに位置するかを、 3つの異なる視点で可視化します。 同じ情報でも見方を変えると気付きが変わります。

📍 体系階層のパス

🌐 統計・データサイエンス因果推論因果手法DiD

① 🔗 関係マップ — 「他の手法とどう繋がっているか」

中心に 差分の差分法(DiD) を置き、 そこから IV・傾向スコア・内生性・重回帰・ロジスティック回帰 計 5 個の用語へ、 前提・兄弟・発展形といった関係を矢印で結んでいます。 線がどちら向きかを見れば、 先に読むべき用語あとから読む用語が分かります。 ノードはドラッグで動かせ、 ホイールでズーム、 クリックでその用語のページへ遷移します。

凡例:現在の用語上位カテゴリ兄弟(並列)前提発展形応用先2階層先

② ⭕ 包含マップ — 「どのカテゴリに含まれているか」

大きな円が小さな円を包含する Circle Packing 図。 「差分の差分法(DiD)」は緑色でハイライト

📍現在地:統計・データサイエンス

③ 🌳 ツリーマップ — 「面積で見るボリューム比較」

長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「差分の差分法(DiD)」は緑色でハイライト

🎯 3つのマップの使い分け

マップ 分かること こんな時に見る
🔗 関係マップ手法間の横の関係(前提→発展→応用)「次に何を学べばよい?」 学習順序の判断
⭕ 包含マップ分類体系の入れ子構造(上位⊃下位)「この手法はどんなジャンルに属する?」
🌳 ツリーマップ分野の規模比較(面積=ボリューム)「データサイエンス全体の俯瞰像」

💡 3 つの図は同じ位置関係を別の角度から描いています。 関係マップは DiD隣に何が並ぶかを、 包含マップとツリーマップは 統計・データサイエンス因果手法 → DiD という入れ子の位置を示します。 「因果手法には他に何があったか」を思い出したいときは包含マップを、 「次に何を読むか」を決めたいときは関係マップを開いてください。

🗺 概念マップ — 完全強化版

🔗 隣接手法への橋渡し

「差分の差分法 (DID)」は単独で完結する手法ではなく、 隣接領域と連携することで真価を発揮する。 具体的には次の 3 方向と密接につながる:

DID は介入前後の差を treatment と control で比較し、 共通トレンド仮定下で因果効果を推定。

🌳 手法選択フロー

DID を含む因果推論の手法選択は、 データ構造・処置の入り方・識別仮定の妥当性で決まる。 典型シナリオと候補手法を示す。

典型シナリオ別の手法選択

シナリオ重視する観点候補手法
2 群 × 前後 2 期間のパネル平行トレンド仮定が妥当標準 DID(2×2 / TWFE)
処置時点が群ごとに異なる(staggered)TWFE のバイアス回避Callaway-Sant'Anna / Sun-Abraham
処置単位が 1 つ(例:1 県だけ)対照群を合成で構築合成統制法(Synthetic Control)
平行トレンドが崩れる別の識別戦略が必要IV / RDD / 傾向スコア

選んだ後の検証ステップ

  1. プレトレンド検定: 処置前ダミーの係数が 0 近傍か(イベントスタディ)
  2. 標準誤差: 県単位のクラスタ頑健 SE、 少クラスターならワイルドブートストラップ
  3. プラセボ検定: 偽の処置時点・偽の処置群で効果が出ないか確認
  4. 同時ショック: 処置と同時期の別イベントを制御・議論したか
  5. 頑健性: サンプル期間・対照群・推定量を変えても符号と大きさが安定するか

🎨 直感を深める — 2×2 表の「4 セルには何が混ざっているか」

DiD の心臓部である 2×2 表(上のウィジェットと同じ実測値)を、 処置群対照群と処置前後で切ると 4 つのセルができます。 この 4 セルの各平均が「何の足し算でできているか」を分解すると、 なぜ 2 回引き算するのか(=差の差)が腑に落ちます。 記号は 群固有の水準を α、 その年の時間効果を λ、 求めたい処置効果を τ とします。

 2018(前)実測2023(後)実測中身の分解
処置群(大都市圏 3 都府県)25.0725.38前=αTpre 後=αTpost+τ
対照群(他 44 県)30.3532.01前=αCpre 後=αCpost

反実仮想の言葉で言い換えると、 「処置群がもし処置を受けなかったら 2023 年にどうなっていたか」を 25.07+(対照群の変化 +1.66)=26.73 と見積もり、 実測 25.38 との差 −1.35 を効果と呼んでいます。 対照群は自然実験的に用意した「反実仮想の代理」です。

⚠️ 落とし穴を深める — 「識別を壊す 5 つの脅威」を機序で理解する

上の 落とし穴集を、 推定量にどう効くか(符号の向き)の観点で整理し直します。 とくに DiD 初学者が見落としがちな 時変交絡(time-varying confounder)を明示的に加えます。

脅威 壊すメカニズム 典型的な症状・見つけ方 対策
① 平行トレンド違反
(pre-trend)
処置前から群間で λ の傾きが違う。 その傾き差が処置効果 τ に丸ごと混入。 本ページ ④ のとおり処置前(2012→2018)で傾きが違う。 イベントスタディの処置前係数が 0 から外れる(下表)。 プレトレンド検定、 プラセボ処置年、 群固有の線形トレンド投入、 崩れるなら合成対照・IVRDD へ。
② 処置タイミングのずれ
(staggered)
処置年が群ごとに違うと、 TWFE が「すでに処置された群」を対照に使う禁じられた比較を含む。 重みが負になりうる。 効果が異質かつ時間変化するとき、 TWFE 推定値が個別 ATT の外側・逆符号になる。 Goodman-Bacon 分解で診断。 Callaway-Sant'Anna、 Sun-Abraham、 de Chaisemartin-d'Haultfoeuille 等の現代的 staggered 推定量。
③ 対照群の選択 処置群と異なるダイナミクスを持つ群を対照にすると、 λ の代理が失敗し偽の τ が出る。 対照群を替えると符号・大きさが不安定。 本例の「他 44 県」は大都市圏の代理として粗すぎる。 近い共変量の群に絞る、 傾向スコアで重み付け(DiD と併用)、 単一処置なら合成対照で加重平均の対照を作る。
④ SUTVA 違反
(波及・スピルオーバー)
処置群の効果が対照群に漏れると、 対照群も動き、 差の差が縮む(効果を過小評価)。 県境・通勤圏・サプライチェーンで隣接するほど汚染が強い。 距離別に効果が変わる。 汚染しうる対照を除外、 距離・隣接ダミーで波及を明示的に測る、 空間計量。
⑤ 時変交絡
(time-varying confounder)
群ごとに時間変化する別要因(例:ある年に処置群だけを襲った産業ショック)は、 固定効果でも年ダミーでも吸収されず τ に混ざる。 固定効果は「時間で変わらない群の違い α」しか消せない。 時間で変わる交絡は残る点が盲点。 時変共変量を制御、 同時期の別ショックを別変数化、 期間分割で頑健性確認、 プラセボ結果変数。

💡 要点固定効果(または 変量効果)が消せるのは「時間で変わらない個体差 α」だけ。 ①と⑤はいずれも「時間で変わる群差」であり、 固定効果を入れても自動では消えません。 DiD を『固定効果を入れたから因果』と誤解しない、 が最大の勘所です。 より体系的な位置づけは パネルデータと因果推論を参照(因果推論の全体像・潜在的結果モデルは本サイト内の関連ページ群にも散在)。

🚀 発展を深める — イベントスタディ・TWFE の落とし穴・合成対照法

① イベントスタディ(リード/ラグ係数)— 本ページの −1.36 を「年ごとに分解」する

2×2 DiD は「処置前 1 点・処置後 1 点」に情報を圧縮しています。 これを各年に開いたのがイベントスタディです。 処置年(2018)を基準(係数 0)に固定し、 各年ダミー×処置群の交互作用係数を並べます。 処置前の係数が 0 近傍ならば平行トレンドを支持、 処置後の係数は動的な効果の推移を表します。 下表は SSDSE-B-2026 の実測群平均から算出した、 2 群飽和イベントスタディの係数(=群平均ギャップの 2018 基準正規化。 実測値のみ)です。

201220132014201520162017 2018
基準
20192020202120222023
係数 +1.53+1.44+1.28+0.85+0.64+0.33 0 −0.34−0.85−0.86−1.11−1.36

読み方:処置後 2023 の係数 −1.36 は、 本ページ ②の 2×2 DiD(−1.36)と一致します(イベントスタディの「処置年基準・特定年係数」は 2×2 DiD の一般化だから)。 ところが処置前の係数が 0 でなく、 +1.53→+0.33 と単調に下がっています。 これは処置前から両群のギャップが縮み続けていた(=平行トレンドが成り立っていない)動かぬ証拠で、 −1.36 の相当部分は処置ではなく既存トレンドの延長である疑いが濃厚です。 実務では、 処置前係数が 0 近傍に収まっているかを図で示すことが、 DiD の信頼性の生命線になります。 → 平行トレンド。 なお本例はあくまで手法デモ(疑似 DiD)であり、 実在の政策効果ではありません。

② 二元固定効果(TWFE)の落とし穴 — 異質処置効果でのバイアス

「個体固定効果+年固定効果+処置ダミー」の TWFE 回帰は、 全群が同時に処置される 2×2 設計では 2×2 DiD と厳密に一致します(本ページ ③)。 しかし処置年が群ごとに異なる staggered 設計では話が変わります。 Goodman-Bacon (2021) は、 TWFE 推定値が「多数の 2×2 比較の加重平均」に分解でき、 その中に「すでに処置された群」を対照に使う禁じられた比較が混じることを示しました。

※ 本ページの疑似 DiD は「全処置群が 2018 年に同時処置」の設計なので、 この staggered バイアスは生じません(③で FE 入り係数が 2×2 と一致するのはそのため)。 上記は「もし処置年がバラバラだったら」という一般論としての注意です。

③ 合成対照法(synthetic control)への橋渡し

処置単位が 1 つしかない(例:ある 1 県だけが政策を導入)とき、 「どの 1 県を対照にするか」で結果が揺れます。 合成対照法はこの選択を、 複数の対照候補の加重平均で「合成された対照単位」を作ることで自動化します。 重みは処置前の結果変数(と共変量)の軌跡が処置単位に最もよく一致するように決めます。

📝 関連ページ(html/glossary 内・実在確認済):平行トレンドパネルデータと因果推論固定効果変量効果パネルデータ自然実験内生性操作変数法(IV)回帰不連続(RDD)処置群対照群選択バイアス交絡因果関係A/B テスト。 なお 合成対照法・イベントスタディ・傾向スコア・因果推論総論・潜在的結果モデルの独立ページは現時点で未作成のため、 本文中でテキスト説明としています。