この用語と一緒に検索・参照されやすいタグ。 関連ページに飛ぶときの手がかりにも使えます。
「平行トレンド仮定」を理解するうえで必要なキーワードを 10 件以上提示します。 各チップから対応セクションへ移動できます。
30 秒結論 文脈 直感 数式 記号読み解き 実値計算 Python 実装 落とし穴 関連手法 関連用語 グループ教材 概念マップ
🍰 まずはやさしく
データの動きが同じ方向に向かうという約束です。
ある対策の効果を正しく測るために使います。
スマホの利用時間をクラスで比べる時に役立ちます。
この章では結論を短くまとめて解説します。
平行トレンド仮定は、 差分の差(DiD)法における核心仮定。 「介入が無ければ処置群と対照群は平行に推移したはず」。
ここまでが要点です。 ただし実際に使う前に、 このページの「⚠️ よくある落とし穴」で挙げた プリトレンドを「目視で平行」と判断/時間変化する交絡 (TWFE 推定量の罠)/Staggered adoption の負の重み には必ず目を通してください。 つまずくのは知識が無いときより、 知ってはいたが確認を飛ばしたときです。
🍰 まずはやさしく
分析の説得力を決める大切なルールです。
本当の原因を突き止めるために使います。
部活の新しい練習法で成績が変わったか調べます。
この用語がどんな場面で登場するかを説明します。
本サイトの政策効果分析(最低賃金、 教育改革等)で頻出。 観察データから因果を語る数少ない手段の一つで、 仮定の妥当性が論文の説得力を左右します。
この用語は一見すると単独で理解できそうに見えますが、 実際には前提となる概念(測定・尺度・サンプリングなど)と組合せて初めて意味を持ちます。 「定義を覚える」より「どんな問いに答える道具なのか」を捉えるのが効率的です。
このセクションは「平行トレンド仮定」を扱う 用語ページ です。 統計データ分析コンペティション(2026)の再現教材における中核用語のひとつで、処置前期間の人口推移 (A1101) で群間の傾きが平行か検証 という観点で SSDSE-B-2026(47 都道府県 × 複数年 × 100 超列)に紐づけられます。
位置づけ:相関・線形回帰・仮説検定 といった基礎用語群と並列であり、応用としては 内生性・IV・DID・クラスタリング 等へ繋がります。
🍰 まずはやさしく
並走する陸上競技のようなイメージです。
もし対策をしなかったらどうなったかを考えます。
テスト勉強法を変えなかった時の点数を想像します。
直感的にイメージを掴むための例を紹介します。
「平行トレンド仮定」を最初に学ぶときは、 厳密な定義よりイメージを優先しましょう。 以下は具体例・比喩を用いた直感的理解の入口です。
平行トレンド仮定 を一言でいえば「処置がなかったと仮定したとき、 処理群と対照群の結果変数 (例: 人口、 出生数、 失業率) が同じ傾きで時間変化するはずだ」 という前提条件。 DID 推定はこの仮定の上で初めて『処理効果 τ』 を解釈できる、 因果推論の根幹となる仮定です。
SSDSE-B-2026 の縦断データ (2012-2023 の年次列) で考えると、 例えば「2020 年に政令市移行した A 市群」 と「移行しなかった B 市群」 の 2014-2019 の人口推移を重ねたとき、 線が並走していれば平行トレンドが成り立つ、 一方が急減・他方が緩減なら平行トレンドは破れていると判定します。 視覚的判定 + 事前期間の交互作用項検定の両方が必須です。
平行トレンドの判別は、 統計検定だけでなく事前期間のトレンドプロットを目で見る ことも重要です。 以下に典型 4 パターンを整理します。
| パターン | 事前トレンド | DID 有効性 | 対応 |
|---|---|---|---|
| ① 理想的 | 処理群・対照群とも同じ傾き | ○ 標準 DID 可 | そのまま実行 |
| ② 平行ずれ | 傾きは同じ、 切片が違う | ○ DID で吸収 | そのまま実行 |
| ③ 発散傾向 | 処理群がもともと急減 | × DID 不可 | Honest DID / Synthetic Control |
| ④ 収束傾向 | 差が縮まっていく | × DID 不可 | マッチング DID |
SSDSE-B-2026 では、 東京圏 (1人あたり所得高、 人口減弱) と東北 (1人あたり所得低、 人口減強) のように経済構造が違う群を比較する場合、 ② や ③ が出やすい。 事前期間が短いと検定の検出力が低いため、 「視覚的に平行に見える + 検定で有意差なし」 の両条件をクリアして初めて平行トレンドが信頼できると考えます。
SSDSE などの公的データで DID を回す前に、 必ず以下 11 項目を確認しましょう。
11 項目すべてクリアして初めて、 「平行トレンドのもと推定された政策効果は τ である」 と論文・レポートに書けます。 教育用 SSDSE 演習でも、 これらの確認手順を再現することで、 因果推論の方法論を身体化できます。
DID 推定が広く認知されたのは、 1994 年の Card-Krueger の最低賃金研究が画期となります。 ニュージャージー州が最低賃金を引き上げたとき、 隣接ペンシルベニア州を対照群として「ファストフード店の雇用が減ったか」 を DID で推定。 古典理論では雇用減少が予測されていましたが、 実際には雇用は減らなかったという衝撃的な発見をもたらしました。 この研究で David Card は 2021 年ノーベル経済学賞を受賞しました。
| 研究 | 処理 | 対照 | 平行トレンド検証 |
|---|---|---|---|
| Card-Krueger (1994) | NJ 最賃引上げ | 隣接 PA 州 | 事前期間の雇用率推移で確認 |
| Acemoglu-Linn (2004) | 市場サイズ拡大 | サイズ不変薬剤 | 新薬承認数を 1970-2000 で比較 |
| Dustmann 他 (2017) | ドイツ最賃導入 | 既に最賃あり地域 | 2009-2014 で事前比較 |
| Bharadwaj 他 (2014) | 新生児医療基準 | 基準前出生児 | 出生体重別 RD-DID |
これらの研究の共通点は、 「処理が外生的に決まった」 こと、 「事前期間のトレンドプロットを論文に必ず掲載した」 こと、 そして「複数の感度分析(プラセボ検定、 別対照群との比較)」 を行ったことです。 SSDSE で同様の手順を踏むなら、 演習として「2014-2019 を事前期間、 2020-2023 を事後期間」 と固定し、 47 都道府県のうち地域ブロック単位で処理/対照を組み合わせるのが安全です。
| 項目 | 内容 |
|---|---|
| 定義 | DID で「処理がなかった場合のトレンドが処理群・対照群で等しい」 と仮定すること |
| 数式 | $E[Y_{0,t} - Y_{0,t-1} \mid D=1] = E[Y_{0,t} - Y_{0,t-1} \mid D=0]$ |
| 検証方法 | 事前期間でトレンド差を OLS の交互作用項で検定、 視覚的に平行性確認、 プラセボ検定 |
| 破れたら | Synthetic Control / Honest DID / Synthetic DID / マッチング DID へ切替 |
| Python | statsmodels.formula.api / linearmodels.panel.PanelOLS / DoubleML |
| SSDSE 演習 | 縦断 2012-2023 で 47 県を地域ブロック単位に組み、 事前期間 8 年分で検定 |
平行トレンド仮定は「観察データから因果効果を推定する」 ための最も古典的かつ強力な仮定の一つです。 完全な検証は不可能ですが、 事前期間のトレンドプロット + 検定 + プラセボの三点セットを習慣化すれば、 99% のケースで「仮定が成り立つ/壊れている」 を見抜けます。 因果推論の入り口として、 必ず手を動かして体感してください。
平行トレンド仮定が「観察できる事前期間」 だけで検証されるという制約は、 因果推論の根本的な「反実仮想は観察不可能」 という問題を反映しています。 これに対応する 4 つの考え方を整理します。
2026 年現在、 計量経済学者の多くは「平行トレンド仮定は厳密には成り立たないが、 sensitivity analysis でロバストにする」 というスタンスをとっています。 SSDSE 演習でも、 古典 DID の結果を出した後、 必ず「もし平行トレンドが ±X% ずれていたら結論がどう変わるか」 まで計算する習慣をつけましょう。
最後に重要な注意: 平行トレンド仮定は「処理効果の異質性 (heterogeneity)」 ともセットで考える必要があります。 ある処理が「効果が大きい県」 と「効果がない県」 で混在するとき、 単純な DID は加重平均効果を返しますが、 weights が直感に反する負の値を持つことがあります(特に staggered adoption 時)。 これが Goodman-Bacon (2021) の指摘した DID の落とし穴で、 2020 年以降の文献で大きな議論となりました。
SSDSE 縦断データで DID を演習する際は、 まず単純な 2×2 DID(処理群 1 グループ vs 対照群 1 グループ、 単一処理タイミング) から始めるのが最も誤解を避けやすいです。 慣れてきたら、 県別に処理タイミングが違う staggered adoption 状況、 複数処理が重なる multiple treatments 状況など、 より複雑なケースへ広げていきましょう。 そのとき、 「平行トレンドが何を意味するか」 という出発点を絶対に忘れないことが肝心です。
ここでは平行トレンド仮定の理解を視覚的に深めるため、 SSDSE-B-2026 都道府県データから 3 種類の図を提示します。 各図は 事前トレンドの平行性検証、 処理群と対照群の事前期間分布、 複数群比較の箱ひげ という 3 つの異なる角度から、 仮定がどのように「目で確認」 されるかを示しています。
このプロットでやること: SSDSE-B-2026 から、 仮想的に「政策処理を 2018 年に受けた都市部 5 県」 と「対照群の地方部 5 県」 を比較。 2012〜2017 年の出生数(A4101) を散布図で並べ、 平行に推移しているかを視認します。

読み方: 横軸が年(事前期間)、 縦軸が出生数(人)。 処理群(青)・対照群(オレンジ) の 2 群の傾きが平行なら、 平行トレンド仮定の信頼度が高い。 もし傾きが交差していれば、 「対照群を反実仮想として使う」 という DID の前提が崩れるサインです。
実務 Tips: 散布図は事前期間 5 年以上をプロットするのが理想。 短すぎると偶然の一致と区別できません。 また、 同じスケールで縦軸を表示すること(処理群と対照群を別の y 軸にしない) が重要です。 別軸にすると平行に「見えてしまう」 視覚的トリックが生じます。
このプロットでやること: SSDSE-B-2026 で、 処理群と対照群の事前期間の「水準」 と「ばらつき」 を比較。 ヒストグラムで両群の分布形状を重ねて表示し、 「そもそも比較可能なくらい似た集団か」 を確認します。

読み方: 横軸が出生数(人)、 縦軸が頻度。 処理群の分布が極端に右にずれていたり、 ばらつきが対照群の数倍だったりすると、 「水準は違うがトレンドは平行」 という主張が苦しくなります。 平行トレンド仮定は「水準が同じ」 を要求しませんが、 「水準が極端に違う場合、 トレンドの解釈も難しくなる」 のは事実です。
判断基準: 両群の分布の中央値が 2 倍以上離れていたら、 マッチングや synthetic control など、 より洗練された手法の併用を検討すべきです。 SSDSE 演習では「東京・大阪のような大都市」 と「地方県」 を混ぜるとこの問題が起きやすいので、 群分けの際に注意してください。
このプロットでやること: SSDSE-B-2026 を 4 グループに分け(処理群・対照 A・対照 B・対照 C)、 事前期間 5 年間の「年次成長率」 を箱ひげ図で比較。 中央値と四分位範囲が群間で揃っていれば、 どの対照群を選んでも平行トレンドが成り立つ証拠となります。

読み方: 横軸が群(処理・対照 A/B/C)、 縦軸が年次成長率(%)。 箱の中央値と高さ(IQR) が群間でほぼ揃っていれば、 「どの対照を選んでも平行トレンドは保証される」 と言えます。 逆に処理群だけ中央値が外れているなら、 平行トレンド違反の疑いが強い。
応用: この箱ひげ図は「どの対照群を採用すべきか」 の判断材料にもなります。 処理群と中央値が最も近い対照群を選ぶことで、 平行トレンド仮定の妥当性を高められます。 ただし、 選び方を恣意的にすると「都合の良い結果」 が出やすくなるので、 事前登録(pre-registration) の精神で群分けルールを決めておくことが推奨されます。
平行トレンド仮定は、 統計学的には「処理群の counterfactual outcome trend(もし処理を受けなかったらどう推移したか) は、 観察された対照群の outcome trend で代替できる」 という主張に対応します。 これは 潜在結果フレームワーク(Rubin Causal Model) における「処理群と対照群の reactive bias が時間方向に一定」 という前提と等価です。
数学的には、 処理群の処理時の潜在結果を $Y_{it}(1)$、 処理を受けなかった場合の潜在結果を $Y_{it}(0)$ とすると、 平行トレンド仮定は次のように書けます。 $E[Y_{it}(0) - Y_{i,t-1}(0) \mid D_i = 1] = E[Y_{it}(0) - Y_{i,t-1}(0) \mid D_i = 0]$。 つまり「処理を受けなかった場合の outcome 変化の期待値」 が、 処理群と対照群で等しい。 これが「平行」 の正式な数学的意味です。
この仮定の重要な性質は scale-dependence です。 同じデータでも outcome を「水準(Y)」 で測るか「対数(log Y)」 で測るか、 「成長率(ΔY/Y)」 で測るかによって、 平行トレンドが成立する尺度が異なります。 SSDSE で出生数を扱う場合、 都市と地方では水準が 10 倍以上違うことがあるので、 log 変換が推奨されることが多いです。 ただし log は 0 や負の値を扱えないので、 outcome の性質を踏まえて選ぶ必要があります。
また、 平行トレンド仮定は 「処理がランダムに割り当てられた」 という強い仮定の弱体版 です。 完全ランダム化が無理な現実世界で、 「水準は違ってもよいが、 トレンドは平行」 という条件で因果効果を推定できる、 というのが DID の魅力。 ただし、 弱体化した分、 トレンドが本当に平行かを「目視 + 統計テスト + sensitivity analysis」 の三段構えで確認する必要があります。
2020 年代の最新の議論では、 平行トレンド仮定を「全期間で完全成立」 ではなく「limited violation(限定的な違反) を許容」 する Honest DID(Rambachan-Roth 2023) が主流になりつつあります。 事前期間で観察されたトレンド差の最大値 M を計算し、 「事後期間でも差が ±M 以内」 という弱仮定で、 効果推定値の正直な信頼区間を構築します。 SSDSE のような短期パネルでも適用可能で、 R や Python の HonestDID パッケージで実装できます。
さらに、 staggered adoption(処理タイミングが群間で異なる) の場合、 二元固定効果回帰(TWFE) は 負の重み を含む集計量となり、 平均処理効果と一致しないことが Goodman-Bacon (2021) と De Chaisemartin-D'Haultfœuille (2020) で示されました。 これに対する処方箋として、 Callaway-Sant'Anna (2021) の did パッケージ、 Borusyak et al. (2024) の did_imputation 推定量などが提案されており、 SSDSE の多時点処理データに DID を適用する際は、 これらの新世代推定量を使うのが標準です。
最後に、 平行トレンド仮定は 「対照群選択の妥当性」 と表裏一体 です。 「対照群を変えたら結果が変わる」 のは仮定違反のサイン。 SSDSE 演習では、 (a) 全 47 都道府県を対照に使う、 (b) 地理的に近い 5 県だけを使う、 (c) 経済規模で類似する県だけを使う、 という 3 通りで DID を回し、 結果が概ね一致するかを確認する習慣をつけましょう。 結果が極端に変わるなら、 「どの対照群が反実仮想として最も妥当か」 を改めて議論する必要があります。
以下の 8 問は、 平行トレンド仮定を実務で正しく使えるかを問うチェックリストです。 すべてに即答できれば、 DID 分析を「形式的に回す」 段階から「自分で妥当性を判断する」 段階へ進めたサインです。 答えは下の解説欄を参照してください。
8 問中 6 問以上正解できれば「実務で DID を回せる」 レベル、 4-5 問なら「教科書理論は分かっているが実装で詰まる」 レベル、 3 問以下なら「もう一度直感セクションに戻って」 という目安です。 SSDSE の縦断データを使った演習を 3 回ほど通せば、 自然と全問正解できるようになります。
ここでは SSDSE-B-2026 の都道府県データ(47 県 × 約 10 年) を使って、 平行トレンド仮定の検証を「実装レベル」 で示します。 仮想的な処理シナリオとして、 「2018 年に 5 県が地方創生交付金の重点配分を受けた」 という設定で、 出生数(A4101) を outcome に使います。
処理群の選定: SSDSE-B-2026 から、 仮想的に「2018 年に重点配分を受けた 5 県」 として東北 4 県 + 北海道を想定。 対照群は「重点配分対象外の 5 県」 として、 同様に地方の中規模県を想定します。 実際には政策評価データが必要ですが、 学習目的では「仮想シナリオ」 で構いません。
事前期間の検証ステップ: (1) 両群の年次平均 outcome をプロットし、 2010〜2017 年の傾きが平行かを目視。 (2) 両群の年次成長率を計算し、 t 検定で「事前期間の平均成長率が群間で等しい」 を検証。 (3) Granger テストで「事前期間の outcome ダイナミクスが群間で似ているか」 を統計的に判定。 これら 3 段階を通過してから DID 本体の推定に進みます。
実装上の落とし穴: SSDSE-B-2026 のデータは年次のため、 季節調整は不要ですが、 「経年変化と政策ショックを区別する」 工夫が必要です。 例えば 2011 年は東日本大震災、 2020 年はコロナショックという外的要因があるので、 これらの年を含む期間で DID を回す際は、 「政策効果」 と「ショック反応」 が分離できているかを慎重に確認します。 通常は時期ダミーや region × time の固定効果を追加して対処します。
推奨される報告フォーマット: DID の結果を報告する際は、 (a) 事前期間の平行トレンドプロット、 (b) Granger テストの p 値、 (c) DID 推定値とその標準誤差、 (d) sensitivity analysis(HonestDID) の結果、 を必ずセットで提示。 (a) と (b) が抜けていると「仮定違反かどうかも分からないまま、 何かの数値だけ提示された」 という不信を招きます。 SSDSE 演習でレポートを書く際も、 この 4 点セットをテンプレートとして持っておくと評価が安定します。
クロスチェックの方法: DID の結果が信頼できるかは、 「対照群を変えても結果がほぼ同じ」 を確認することで検証できます。 具体的には、 (i) 全 47 県を対照群として用いる、 (ii) 処理群と地理的に近い 5 県を対照群にする、 (iii) 経済規模で類似する 5 県を対照群にする、 という 3 通りの設定で DID を回し、 推定値が ±20% 以内に収まるかを確認。 大きく異なる場合、 「どの対照群が反実仮想として妥当か」 を再検討する必要があります。
長期効果と短期効果の分離: SSDSE-B-2026 は年次データなので、 処理の「即時効果(処理開始 1 年目)」 と「定着効果(3-5 年後)」 を分離できます。 Event study プロットで処理開始前後の係数を時点別に推定すると、 (i) 処理前は係数 ≈ 0 で平行トレンドが成立、 (ii) 処理開始時に大きく動く、 (iii) その後安定または減衰、 というパターンが典型。 このパターンと外れる場合(例: 処理前から係数が動いている)、 「内生性疑い」 として報告する必要があります。
感度分析の実装: HonestDID パッケージ(Python: pyhonestdid、 R: HonestDiD) を使うと、 「平行トレンド違反の最大値 M がどれくらいなら DID 推定値の信頼区間が 0 を含むか」 を逆算できます。 例えば M = 0.5%/year(事前で観察されたトレンド差の最大値の半分) まで許容しても結論が変わらない、 と言えれば「結果は頑健」 と主張できます。 SSDSE 演習の発展課題として、 この感度分析まで含めると専門家レベルです。
因果効果の経済的意味づけ: 統計的に有意な DID 推定値が得られたとして、 それが「経済的に意味のある大きさ」 かを評価することも重要です。 SSDSE-B-2026 の出生数は県ごとに数千〜十万人規模のスケールなので、 例えば DID 推定値が「年間 +200 人」 なら政策対象の人口規模や予算と対比し、 「政策費用と比較して投資効率は妥当か」 まで議論できると、 単なる統計分析を超えた政策評価レポートになります。
平行トレンド仮定の核心は「処置前トレンドの傾きが両群で等しいか」です。 ここでは処置前トレンドの傾き差(=仮定の崩れ)と真の処置効果 τをあなたが動かし、 DID 推定値がどれだけバイアスを持つか、 そしてイベントスタディの処置前係数がゼロ近傍か(プラセボ検定)を体感します。 計算はすべて解析式どおり正確です。
💡 上のグラフを上下にドラッグ/スワイプしても傾き差 δ を変えられます(タッチ対応)。
基準は処置直前 k=−1(β−1=0 に固定)。 処置前(k<0)の点がゼロ線の近くに並べばプラセボ検定に合格=平行トレンドを支持。 δ を動かすと処置前の点がゼロから傾いて離れる様子が見えます。
δ ×(処置後の平均相対時点)で、 処置前の傾き差 δ が 0 なら 2 本の反実仮想が一致し、 DID 推定値=真の τ。 δ が大きいほど推定は真値から系統的にずれる。関連ページ:差分の差分法(DID)/パネル因果推論/固定効果/自然実験。 (イベントスタディ・合成統制法は本用語集に独立ページがまだ無いため、 リンクではなく用語として示しています。)
🍰 まずはやさしく
数式で表した厳密なルールです。
計算して正しく答えを出すために使います。
買い物で使う金額の変化を数式にします。
記号の意味と数式の読み方を詳しく解説します。
直感の次は、 厳密な定義を確認します。 数式は言語の一種で、 一度書き慣れれば「言葉より速く伝えられる」便利な道具。 慣れていない方は、 各記号が何を表すかを「🔬 数式を言葉で読み解く」で 1 つずつ確認してください。
平行トレンド仮定 の代表的な定義式は次のとおりです。
$$ \mathbb{E}[Y_{i,t}^{0} - Y_{i,t-1}^{0} \mid D_i=1] = \mathbb{E}[Y_{i,t}^{0} - Y_{i,t-1}^{0} \mid D_i=0] $$ここで使われる記号や演算の意味は次節で言葉に翻訳します。
数式を眺めるだけでは身につかないので、 各記号がどんな役割を担っているかを言葉で押さえます。 「数式を音読する習慣」がつくと、 論文や教科書を読むスピードが体感で 2 倍ほど上がります。
数式の各記号を、日本語の意味に変換します。
平行トレンド仮定は、 DID(差分の差)分析の最重要前提です。 「処置を受けなかった場合の処置群と対照群の時系列トレンドが平行である」という反事実的仮定で、 検証不可能ですが、 事前期間のトレンド一致でサポートできます。
平行トレンド仮定 (Parallel Trends Assumption) は、 統計・データ解析の文脈で頻繁に登場する概念です。 ここでは初学者向けの直感と、 上級者向けの形式定義を併記します。
2018-2020 年と 2020-2023 年で、 処置群(例:補助金導入県)と対照群(非導入県)の出生率トレンドを比較。 事前期間(2018-2020)で両群の傾きが類似していれば、 平行トレンド仮定が支持される。 SSDSE-B-2026 の年度別パネルで複数年の時系列を可視化することが必須。
SSDSE-B-2026 は 都道府県別社会経済データ集 2026 年版で、 47 都道府県 × 約 10 年度 × 100 超の指標を含む公的データです。 平行トレンド仮定の概念を SSDSE-B-2026 で実証することで、 「数値の動きが地理的・社会的直感と整合するか」を検証できます。
| 列コード | 意味 | 本ページでの用途 |
|---|---|---|
A1101 | 総人口 | 県別人口トレンドの確認 |
A4101 | 出生数 | 少子化対策 DID の outcome |
A4103 | 合計特殊出生率 | 出生施策の効果指標 |
L3221 | 消費支出(二人以上の世帯) | 家計への政策波及の指標 |
平行トレンド仮定の式 $E[Y_{0,t} - Y_{0,t-1} \mid D=1] = E[Y_{0,t} - Y_{0,t-1} \mid D=0]$ は、 短いですが、 各記号が因果推論の「反実仮想 (counterfactual)」 を表現する核心です。 数式を言葉で読み解くと、 次のような構造です。
| 記号 | 読み | 意味 | SSDSE 例 (人口政策 DID) |
|---|---|---|---|
| $Y_{0,t}$ | ワイ・ゼロ・ティー | 処理を受けなかった場合の時点 t の潜在結果(観察できない反実仮想) | 「2020 年に政策がなかった場合の出生率」 |
| $D$ | ディー | 処理の有無 (1 = 処理群、 0 = 対照群) | 出生支援策を導入した県 = 1 |
| $Y_{0,t} - Y_{0,t-1}$ | 変化量 | 処理なしでの「自然な時間変化」(トレンド) | 少子化の進行幅 |
| $E[\cdot \mid D=1]$ | 条件付き期待値 | 処理群における平均 | 政策導入県の平均的な変化 |
数式を言葉で読み解く視点 1: 反実仮想の等価性 この式は、 「処理を受けた群が処理を受けなかった場合の変化幅は、 実際に処理を受けなかった群の変化幅と等しい」 という主張です。 つまり対照群の時間変化が「処理群の counterfactual トレンド」 の代理になるという仮定。 これが破れると DID 推定はバイアスを持ちます。
数式を言葉で読み解く視点 2: 二重差分 (Difference-in-Differences) との対応 DID 推定量 $\widehat{\tau}_{DID} = (Y_{1,\text{post}}^T - Y_{1,\text{pre}}^T) - (Y_{0,\text{post}}^C - Y_{0,\text{pre}}^C)$ は、 「処理群の事後・事前差」から「対照群の事後・事前差」 を引いて「政策効果」を抽出します。 もし平行トレンド仮定が成り立てば、 後者は「事後の counterfactual トレンド」 として処理群の自然変化を表し、 差し引きで純粋な処理効果が残るわけです。
数式を言葉で読み解く視点 3: 検証不能だが反証可能 平行トレンド仮定は処理後の counterfactual を含むため厳密には検証不能ですが、 処理前期間では両群とも観察できるので、 「事前期間のトレンドが平行であった」 という形で間接的に支持・反証することができます。 これが pre-trend test の役割。
数式だけでは「実感」が湧きにくいので、 具体的な数値で 1 度手計算してみると理解が定着します。 以下の例は、 本サイトで扱う SSDSE-B-2026 や公開教材に近い形式で用意しました。
2 群×2 期の DiD 推定の構造:
| 群\期 | 介入前 | 介入後 | 差 |
|---|---|---|---|
| 処置群 | 100 | 130 | +30 |
| 対照群 | 100 | 110 | +10 |
| 差の差 | — | — | +20 = ATT |
「平行トレンドが成り立つ」前提で、 +20 が介入の因果効果。 介入前のトレンドが既にズレていれば +20 は信用できない。
手計算で得た値と、 後述の Python 実装で算出した値が一致することを確認すると、 「数式とコードの対応関係」がクリアに見えるようになります。
SSDSE-B-2026(公的統計の社会・教育系データセット、 47 都道府県 × 10 年分超 × 100 以上の列)を用いて、 「平行トレンド仮定」を体感します。 ファイル名は SSDSE-B-2026.csv、 読み込みは下記の Python コードで行います。
1 2 3 4 5 6 7 8 | import pandas as pd # SSDSE-B-2026 を読み込む(cp932 / Shift_JIS) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='cp932') print(df.shape) # (564, 112) print(df['SSDSE-B-2026'].unique()) # 含まれる年度 latest = df[df['SSDSE-B-2026'] == df['SSDSE-B-2026'].max()].copy() print(latest[['Prefecture', 'A1101', 'A4101']].head()) |
SSDSE-B-2026 の A1101 (総人口) は DID 演習で結果変数として最頻出。 平行トレンド検証の手順例:
このコードでやること: SSDSE-B-2026 (2012-2023 縦断) の出生数を用い、 「東京圏(東京・神奈川・埼玉・千葉)」 を処理群、 「東北 6 県」 を対照群と仮設定して、 事前期間の平行トレンドが成り立つかを線形回帰の交互作用項で検定します。
📥 入力例: SSDSE-B-2026.csv の出生数列を年・地域 別パネル形式へ整形
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import pandas as pd import statsmodels.formula.api as smf df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df.rename(columns={'SSDSE-B-2026': '年度', 'Prefecture': '地域', 'A4101': '出生数'}) treat = ['東京都', '神奈川県', '埼玉県', '千葉県'] control = ['青森県', '岩手県', '宮城県', '秋田県', '山形県', '福島県'] df = df[df['地域'].isin(treat + control)].copy() df['group'] = df['地域'].isin(treat).astype(int) # 事前期間(〜2019 年)で平行トレンドを検定 pre = df[df['年度'] < 2020] model = smf.ols('出生数 ~ 年度 * group', data=pre).fit() print(model.summary().tables[1]) |
📤 実行例
💬 結果の読み方 交互作用項「年度:group」の p 値 = 0.600。 これが「事前トレンドの傾き差」 を表す係数で、 有意でない (p > 0.05) ため、 「東京圏と東北 6 県の出生数低下速度に統計的差はない」 = 平行トレンドが成り立っていると判断できる。 これで、 「2020 年以降の処理(仮設の政策) 効果を DID で推定する」 ことが正当化されます。 もし交互作用項が有意なら、 そもそも DID は使えない(dynamic DID や event study が必要) という結論になります。
このコードでやること: 平行トレンドの仮定を統計的検定だけでなく「視覚的」 にも確認するための event-study プロット作成例です。 SSDSE 縦断データで、 処理タイミング前後の係数を線でつなぎ、 「事前は平行、 事後は処理効果で乖離」 が現れるかを確認します。
📥 入力例: 年度 × 地域 のパネル、 処理タイミング = 2020 年
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import pandas as pd import statsmodels.formula.api as smf df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df.rename(columns={'SSDSE-B-2026': '年度', 'Prefecture': '地域', 'A4101': '出生数'}) treat = ['東京都', '神奈川県', '埼玉県', '千葉県'] control = ['青森県', '岩手県', '宮城県', '秋田県', '山形県', '福島県'] df = df[df['地域'].isin(treat + control)].copy() df['group'] = df['地域'].isin(treat).astype(int) # 基準年 2019 に対し、各年ダミー × group の係数を推定 years = sorted(df['年度'].unique()) coefs = [] for y in years: sub = df[df['年度'].isin([2019, y])].copy() sub['post'] = (sub['年度'] == y).astype(int) m = smf.ols('出生数 ~ post + group + post:group', data=sub).fit() coefs.append((y, m.params['post:group'], m.bse['post:group'])) cdf = pd.DataFrame(coefs, columns=['年度', 'τ', 'se']) print(cdf.to_string(index=False)) |
📤 実行例
💬 結果の読み方 2014-2018 の τ は ±230 と小さく、 信頼区間に 0 を含む(平行トレンド成立)。 一方 2020 年以降は τ が大きく負に振れる(処理群の出生数が対照群よりさらに低下)。 これは「事前期間に平行、 事後に差異」 という event study の理想的なシグナル。 ただし 2020 年は COVID-19 と重なるため、 処理効果と他のショックを分離する追加検定が必要です。
このコードでやること: 平行トレンドの仮定が成り立つなら、 「実際には何も起きていない年に偽の処理を入れた DID」 は効果ゼロを推定するはず。 SSDSE 縦断で、 処理年を 2017 年と偽設定して τ を計算し、 「偽効果」 が出るか確認します。
📥 入力例: 2012-2019 の事前期間のみを用い、 仮想処理年 = 2017
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import pandas as pd import statsmodels.formula.api as smf df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df.rename(columns={'SSDSE-B-2026': '年度', 'Prefecture': '地域', 'A4101': '出生数'}) treat = ['東京都', '神奈川県', '埼玉県', '千葉県'] control = ['青森県', '岩手県', '宮城県', '秋田県', '山形県', '福島県'] # 事前期間(〜2019 年)だけを使い、偽の処理年 2017 を仮定 df = df[df['地域'].isin(treat + control) & (df['年度'] < 2020)].copy() df['group'] = df['地域'].isin(treat).astype(int) df['placebo_post'] = (df['年度'] >= 2017).astype(int) m = smf.ols('出生数 ~ placebo_post * group', data=df).fit() print(m.summary().tables[1]) |
📤 実行例
💬 結果の読み方 placebo_post:group の係数 = -4045.5、 p = 0.596 で 有意でない。 つまり「事前期間内の偽の処理タイミング」 では DID は効果を検出しない → 平行トレンドが成り立っていることをさらに裏付ける。 もし placebo 効果が有意に出てしまうと、 本来の DID 結果は「未観察の交絡(経済ショック、 人口流出)」 を拾っている疑いが高まります。
合成データで政策前 3 期の処置/対照群トレンドを比較する。
| 期 | 処置 | 対照 | 差 |
|---|---|---|---|
| t=-3 | 10 | 8 | 2 |
| t=-2 | 12 | 10 | 2 |
| t=-1 | 14 | 12 | 2 |
1 2 3 4 5 6 7 | import numpy as np treat = np.array([10, 12, 14]) ctrl = np.array([8, 10, 12]) diff = treat - ctrl print(f"群間差: {diff}") print(f"差の分散: {diff.var()}") print(f"平行: {diff.var() < 0.01}") |
💬 手計算 (Step 2) と Python 出力が完全一致。 完全平行。
公的統計(SSDSE-B-2026)を題材に、 最小限の Python コードで動作させます。 ファイルパス(data/raw/SSDSE-B-2026.csv)は自分の環境に合わせて変更してください。 まずはこのまま動かすことが理解の最短ルートです。
1 2 3 4 5 6 7 8 9 10 11 | import pandas as pd import statsmodels.formula.api as smf df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df.rename(columns={'SSDSE-B-2026': 'year'}) # 仮想的な処置群フラグ(東京・大阪・愛知 を処置群とする例) df['treated'] = df['Prefecture'].isin(['東京都', '大阪府', '愛知県']).astype(int) df['post'] = (df['year'] >= 2022).astype(int) df['did'] = df['treated'] * df['post'] model = smf.ols('A4101 ~ treated + post + did', data=df).fit() print(model.summary().tables[1]) # did の係数が ATT |
▶ 実行 を押せばこのページの中でそのまま動きます(ライブラリもデータも同梱済みで、 準備は要りません)。 手元の Python に移して動かすときは pip install numpy pandas scikit-learn scipy statsmodels が必要です。 読んでいるデータは data/raw/SSDSE-B-2026.csv。 日本語を含むので encoding='cp932' の指定を落とさないでください。
本サイトの全コードは 論文一覧ページ から実例として確認できます。 自分のデータで試したい場合は、 列名・欠損記号・単位の違いだけ調整すれば、 ほぼそのまま流用できます。
「平行トレンド仮定」を初めて使う方向けに、 ハンズオン的な実行手順を整理します。 上の Python 実装と組み合わせて、 1 度自分の手でなぞってみることを強く推奨します。
data/raw/ に配置(または自分のデータを用意)。 列名と単位を確認。df.head()、 df.describe()、 df.isna().sum() で全体像を把握。 ここで欠損や外れ値の見当を付ける。この 8 ステップを 1 度回すと、 「用語を読んで分かった気になる」段階から「実際に使える」段階に進めます。 知識は身体で覚えるのが結局のところ最速です。
scipy / pandas / scikit-learn / statsmodels を中心とした標準的な実装例です。 まず CSV を読み込み、 次に 平行トレンド仮定 の解析を行います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import pandas as pd import numpy as np from scipy import stats df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='cp932') df = df[df['SSDSE-B-2026'] == df['SSDSE-B-2026'].max()].copy() x = df['A1101'].astype(float).values y = df['A4101'].astype(float).values # 基本統計量 print('n =', len(x)) print('mean(x) =', np.mean(x)) print('std(x) =', np.std(x, ddof=1)) # 平行トレンド仮定 の代表的計算(用途に応じて scipy/statsmodels を切替える) r, p = stats.pearsonr(x, y) print(f'Pearson r = {r:.4f}, p = {p:.4g}') rs, ps = stats.spearmanr(x, y) print(f'Spearman rho = {rs:.4f}, p = {ps:.4g}') |
用途別の追加実装:
1 2 3 4 5 6 7 8 9 | # 標準化と簡易クラスタリングの例 from sklearn.preprocessing import StandardScaler from sklearn.cluster import KMeans X = df[['A1101', 'A4101']].astype(float).values Xs = StandardScaler().fit_transform(X) km = KMeans(n_clusters=4, n_init=10, random_state=0).fit(Xs) df['cluster'] = km.labels_ print(df[['Prefecture', 'A1101', 'A4101', 'cluster']].head(10)) |
1 2 3 4 5 6 7 | # 時系列(北海道の A1101)— 例として ARIMA 系の前処理 import statsmodels.api as sm ts = df.sort_values('SSDSE-B-2026').groupby('SSDSE-B-2026')['A1101'].mean() print(ts.tail()) res = sm.tsa.stattools.adfuller(ts) print('ADF stat:', res[0], 'p:', res[1]) |
以下は SSDSE-B-2026 を題材にした実コード例集です。 すべて data/raw/SSDSE-B-2026.csv を読み込み、 実値で動作確認しています。
1 2 3 4 5 6 7 8 | import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis', skiprows=[1]) d23 = df[df['SSDSE-B-2026']==2023].reset_index(drop=True) d23['aging'] = d23['A1303'].astype(float)/d23['A1101'].astype(float) d23['birth_rate'] = d23['A4101'].astype(float)/d23['A1101'].astype(float)*1000 print(d23[['Prefecture','aging','birth_rate']].describe().round(3)) print('最高齢化:', d23.nlargest(3,'aging')[['Prefecture','aging']].values) print('最低高齢化:', d23.nsmallest(3,'aging')[['Prefecture','aging']].values) |
1 2 3 4 5 6 7 8 9 10 11 | import pandas as pd import matplotlib.pyplot as plt df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis', skiprows=[1]) d23 = df[df['SSDSE-B-2026']==2023].reset_index(drop=True) d23['aging'] = d23['A1303'].astype(float)/d23['A1101'].astype(float) fig, axes = plt.subplots(1, 2, figsize=(12, 4)) axes[0].hist(d23['aging'], bins=15, edgecolor='black') axes[0].set_xlabel('高齢化率'); axes[0].set_ylabel('県数') axes[1].boxplot(d23['aging']) axes[1].set_ylabel('高齢化率') plt.savefig('aging_dist.png', dpi=100) |
1 2 3 4 5 6 7 8 9 10 11 12 | import pandas as pd from scipy import stats import numpy as np df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis', skiprows=[1]) d23 = df[df['SSDSE-B-2026']==2023].copy() d23['aging'] = d23['A1303'].astype(float)/d23['A1101'].astype(float) urban = ['R13000','R14000','R23000','R27000','R28000'] # 東京・神奈川・愛知・大阪・兵庫 u = d23[d23['Code'].isin(urban)]['aging'] r = d23[~d23['Code'].isin(urban)]['aging'] t, p = stats.ttest_ind(u, r, equal_var=False) d_cohen = (u.mean() - r.mean()) / np.sqrt((u.var() + r.var())/2) print(f't = {t:.2f}, p = {p:.4f}, Cohen d = {d_cohen:.2f}') |
1 2 3 4 5 | import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis', skiprows=[1]) df['aging'] = df['A1303'].astype(float)/df['A1101'].astype(float) trend = df.groupby('SSDSE-B-2026')['aging'].agg(['mean','std','min','max']).round(3) print(trend) |
平行トレンド仮定は前提条件次第で意味が変わります。 SSDSE-B-2026 のような公的統計では、 サンプリングフレームが「全 47 都道府県」 と完全把握されているため、 通常の標本誤差は発生しません。 しかし「2023 年の 1 時点を全体集団とみなすか、 もっと長期の集団からの 1 サンプルとみなすか」で解釈が変わります。
SSDSE-B-2026 のような 100 超の列を扱うと、 多重比較(同じデータで多数の検定を行う)の罠が発生します。 Bonferroni 補正、 Benjamini-Hochberg などで補正してから 平行トレンド仮定に関連する統計量を解釈すべきです。
都道府県の中に市区町村があり、 階層構造を持つ場合、 階層線形モデル(HLM)で 平行トレンド仮定を扱うことを検討します。 SSDSE-B は都道府県集計データなので階層性は限定的ですが、 SSDSE-D(個票相当)と組み合わせる研究では本格的な階層モデリングが必要です。
SSDSE-B-2026 は 2012〜2023 年の 12 年間のパネル構造を持ちます。 平行トレンド仮定を時間軸込みで扱うときは、 固定効果モデル・ランダム効果モデルなどパネルデータ手法を併用します。
SSDSE-B-2026 の県別データから「平行トレンド仮定に関わる関係」を抽出できても、 それは多くの場合「相関」であり、 「因果」を主張するには無作為化試験・自然実験・操作変数などの追加設計が必須です。
このコードでやること: 計量経済学パッケージ linearmodels の PanelOLS を使い、 SSDSE 縦断データで固定効果付き DID を推定します。 これにより、 「県固有の時間不変な交絡(地形、 文化、 産業構造)」 を吸収できる、 より厳密な DID が実行できます。
📥 入力例: 47 県 × 10 年のパネル、 県と年度を MultiIndex
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import pandas as pd from linearmodels.panel import PanelOLS df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df.rename(columns={'SSDSE-B-2026': '年度', 'Prefecture': '地域', 'A4101': '出生数'}) treat = ['東京都', '神奈川県', '埼玉県', '千葉県'] control = ['青森県', '岩手県', '宮城県', '秋田県', '山形県', '福島県'] df = df[df['地域'].isin(treat + control)].copy() df['D'] = (df['地域'].isin(treat) & (df['年度'] >= 2020)).astype(int) df = df.set_index(['地域', '年度']) m = PanelOLS.from_formula('出生数 ~ D + EntityEffects + TimeEffects', data=df) res = m.fit(cov_type='clustered', cluster_entity=True) print(res.summary) |
📤 実行例
💬 結果の読み方 県固定効果 + 時間固定効果を入れた DID 推定値 τ = -9004 (95% CI: -12480 ~ -5529、 p < 0.0001)。 標準誤差を「県クラスタ」 でロバスト計算しており、 同一県の時間相関を考慮済み。 仮定どおりの平行トレンドが成立しているなら、 「東京圏で 2020 年以降、 政策がなければの自然減と比べて出生数が約 9000 人/年/県さらに減少した」 と解釈できます(実際は COVID 影響等を含むので政策効果単独ではない点に注意)。
下の「実務で本当に困る 7 件」「拡張手法」と重ならない、 SSDSE-B-2026 のような都道府県パネルで DiD を実装する瞬間に詰まる典型を 4 件追加で示す。
平行トレンド仮定 を実務で扱う際に踏みやすい落とし穴を 5 件挙げます。
2020 年代に入り、 平行トレンド仮定の脆弱性に対応する新手法が次々登場しています。 主要な 3 系統を整理します。
| 手法 | 提唱年 | アイデア | 対応する弱点 |
|---|---|---|---|
| Synthetic Control | 2003 (Abadie) | 対照群を加重平均で「合成」し、 処理前ぴったり合わせる | 対照群選択の恣意性 |
| Synthetic DID | 2021 (Arkhangelsky 他) | DID と Synthetic Control を融合、 時間重みも最適化 | 事前トレンド差の頑健化 |
| Honest DID | 2022 (Rambachan-Roth) | 事前トレンド差の最大幅を許容し、 信頼区間を「正直に」 拡げる | 平行トレンドの完全成立を仮定しない |
| Callaway-Sant'Anna | 2021 | 処理タイミングが異なる群の効果を分けて推定 | Staggered adoption の negative weights |
| de Chaisemartin-D'Haultfœuille | 2020 | TWFE 推定量が一般 ATT を表さない問題を診断 | TWFE の解釈問題 |
これらの手法は、 平行トレンド仮定が「グレースケール」 の問題 — 厳密には成り立たないかもしれないが、 そのズレが結果にどれくらい効くか — として扱うパラダイムシフトを反映しています。 SSDSE のような縦断公的統計データを使う際は、 古典 DID に加えて synthetic DID も併用するのが、 2026 年現在のベストプラクティスです。
DID の起源はジョン・スノウ (John Snow) による 1854 年ロンドンコレラ流行調査に遡ります。 スノウは「水源の違う 2 地域の死亡率変化」 を比較し、 飲料水中のコレラ菌仮説を裏付けました。 これは事実上「平行トレンドの仮定」 を暗黙に置いた最初の準実験です。
| 年代 | 人物・出来事 | 貢献 |
|---|---|---|
| 1854 | ジョン・スノウ | ロンドンコレラ調査で DID 的発想 |
| 1985 | Ashenfelter & Card | 職業訓練効果の DID 推定で現代的定式化 |
| 1994 | Card & Krueger | 最低賃金引上げの雇用への効果を DID で分析 |
| 2003 | Abadie | Synthetic Control 法を提唱 |
| 2020-22 | Callaway/Sant'Anna 他 | Staggered DID の理論再整備 |
| 2021 | Card | DID 実証研究でノーベル経済学賞 |
2021 年 David Card のノーベル経済学賞は、 平行トレンド仮定に基づく DID 推定の経済学・社会科学への決定的な影響を認めた出来事です。 仮定の妥当性を吟味する技法も並行して発展し続けており、 「仮定に依存する推論」 のあり方が現代計量経済学の中心課題となっています。
本ページでは「平行トレンド仮定」を 12 セクション(🔖 キーワード索引/💡 30 秒結論/📍 文脈/🎨 直感/📐 数式/🔬 数式を言葉で読み解く/🧮 実値計算/🐍 Python 実装/⚠️ 落とし穴/🌐 関連手法/🔗 関連用語/📚 グループ教材)で完結に整理しました。 SSDSE-B-2026 を素材に、 概念の輪郭・式の意味・実装手順・典型的な失敗パターンの 4 点を最低限押さえれば、 統計データ分析コンペの現場で迷わず使えるはずです。
平行トレンド仮定は DID 推定の前提条件であり、 仮定が破れた場合に隣接手法へ移行する判断軸として機能する。
SSDSE-B-2026 で DID 演習をするときは、 「平行トレンド検証 → 不合格なら合成対照法へ → 合成対照も不安定なら RCT 設計に切替」 という分岐を明示し、 仮定と手法の対応関係を体得することが重要。
| 関係 | 概念 | parallel-trendsとの接続 |
|---|---|---|
| 上位(一般化) | データ分析の方法論全体 | parallel-trendsは分析方法論の 1 構成要素として位置付く |
| 下位(特殊化) | parallel-trendsの具体的応用・拡張版 | SSDSE-B-2026 等の実データへ適用した具体ケース |
| 並列(兄弟) | 同種の代替手法 | 同じ問題を異なる前提・形式で解く類似手法 |
| 前提 | parallel-trendsが依存する基盤概念 | 数学・統計・計算基盤の前提知識 |
| 応用 | SSDSE での具体演習 | 47 都道府県データで parallel-trends を実践する場面 |
SSDSE-B-2026 で「政令市移行年 (例: 熊本 2012、 岡山 2009)」 を処理時点とし、 隣接県を対照群に置いて DID を組む。 平行トレンドは事前期間 3-5 年で出生数の対数推移を OLS 交互作用項で検定。
「移住促進補助金導入県」 を処理群、 「未導入県」 を対照群とし、 SSDSE の若年層人口 (15-29 歳) を結果変数に DID。 平行トレンドが満たされなければ Synthetic Control へ切替。
「医学部地域枠拡大県」 vs 「未拡大県」 で人口あたり医師数の推移を比較。 平行トレンド検証で事前期間 (拡大開始 5 年前) の傾き等価性を確認後、 DID で政策効果を定量化。
Card-Krueger 型の DID を SSDSE 就業者数で再現。 最賃の県別格差を処理強度として活用、 平行トレンドが弱い場合は staggered DID 推定量で対応。
2020 年を共通ショックとし、 観光業比率の高い県と低い県で就業率の DID。 共通ショックは原則として平行トレンドを破る点に注意し、 ショック前のトレンドを慎重に検証する。
研究結果を 平行トレンド仮定を使って報告するときに守るべきチェックリスト:
平行トレンド仮定は学術研究だけでなく、 政策・ビジネスの意思決定に直接活用されています。
計量経済学・教育測定・心理測定・疫学などで 平行トレンド仮定は基礎ツール。 近年は機械学習との融合で新しい応用が広がっています。
平行トレンド仮定 の概念は、 統計学の発展史と並行して洗練されてきました。
日本では、 1947 年の統計法制定以降、 SSDSE-B のような公的統計の整備が進み、 平行トレンド仮定を学ぶ実データ環境が充実してきました。
「平行トレンド仮定」を扱う際の手法選択は、 状況に応じて以下のフローで判断すると迷いが減る。
このフローに沿って判断することで、 「平行トレンド仮定」を中核とした適切な手法選択ができる。
既存の「🎨 直感で掴む」ではレーンの比喩で全体像を示しました。 ここでは別の角度から、 平行トレンド仮定が「反事実(counterfactual)の穴埋め規則」であることを掘り下げます。
DiD が答えたい問いは「処置群に処置がなかったら、 結果はどう推移したか」です。 しかしその世界は絶対に観測できません(同じ主体を同時に処置あり/なしの両方で観測できない、 因果推論の根本問題)。 平行トレンド仮定は、 この観測不能な穴を「対照群が実際に描いた変化量(傾き)で埋めてよい」と宣言する規則です。 だからこそ DiD は「水準の差」ではなく「差の差(変化量の差)」を効果とみなします。
重要なのは、 処置前トレンドの平行性は仮定そのものの検証ではなく「傍証(circumstantial evidence)」に過ぎない点です。 裁判で言えば、 現場から容疑者の指紋が出たようなもの。 有力な状況証拠ではあるが、 犯行を直接目撃したわけではありません。 処置前で平行だったという事実は、 「処置後も平行だっただろう」という信念を補強するだけで、 証明はしません。
平行トレンドは「検定に通ったから OK」で済む仮定ではありません。 既存の落とし穴セクションと重複しない角度で、 特に誤解されやすい7点を整理します。
| 落とし穴 | なぜ危険か | 対処の方向 |
|---|---|---|
| ① 検証不能性 | 反事実(処置がなかった処置群)は原理的に観測できない。 「証明」は不可能で、 できるのは傍証集めだけ。 | 感度分析で「どれだけ違反したら結論が変わるか」を示す |
| ② 前平行≠後平行 | 処置直前まで平行でも、 処置後に別要因で乖離する保証はない(外挿の失敗)。 | 別対照群・別期間での頑健性確認 |
| ③ 対照群の選択 | 恣意的に「平行に見える群」を選ぶと確証バイアス。 選び方で結論が動く。 | 選択ルールの事前登録、 複数対照群で比較 |
| ④ 時間可変交絡 | 処置群だけに効く別ショック(景気・災害・同時期の別政策)が同時進行だと、 効果に混入。 | 共変量調整・イベント時系列の精査 |
| ⑤ 関数形依存 | 水準 $Y$ で平行でも対数 $\log Y$ では非平行(逆も然り)。 平行性は尺度に依存する。 | 結果変数の性質に沿った尺度選択と明記 |
| ⑥ 検定の検出力不足 | 事前期間が短い・分散が大きいと、 本当は非平行でも「有意差なし」で見逃す(第2種の誤り)。 | 検出力・信頼区間を報告、 「有意差なし≠平行」と自覚 |
| ⑦ 予期(anticipation)効果 | 政策の事前公表で、 処置前に主体が行動を変え、 処置前トレンドが歪む。 | 公表時点を処置時点とする、 直前期を基準から外す |
特に強調したいのは⑤と⑥です。 ⑤について、 同じ SSDSE の人口データでも、 都市と地方で水準が10倍違えば「水準の差の差」と「率(対数)の差の差」は別物になります。 「平行トレンドが成り立つかどうか」はデータではなく尺度の選択と一体である、 という点は初学者が最も見落とします。 ⑥について、 逆に47都道府県級の大きなパネルでは検出力が高すぎて、 実務上無視できるほど小さいトレンド差でも「有意」と出やすい(下の SSDSE 実測を参照)。 「p 値が小さい=致命的な違反」でも「p 値が大きい=平行が保証された」でもありません。 傾きの差の大きさを効果量と並べて解釈することが不可欠です。
「平行トレンドは厳密には成り立たない」を出発点に、 2010年代後半以降の計量経済学が整えてきた道具立てを俯瞰します。 用語は本サイトの関連ページ(下節)と対応します。
実務の推奨順序は「イベントスタディで前平行を可視化 → 必要なら共変量調整 → Honest DiD で感応度を報告 → プラセボで駄目押し」。 単一の p 値に頼らず、 複数の角度から仮定の妥当性を束ねるのが現代的作法です。
落とし穴③(対照群の選択)と⑥(検出力)を、 SSDSE-B-2026(47都道府県 × 2012-2023、 cp932)の実データで確認します。 結果変数は総人口 A1101 の対数 $\log(\text{A1101})$、 処置前期間を 2012-2019 とし、 各群の年率トレンド(対数の年次傾き)と、 都道府県固定効果を入れた「年次 × 群」交互作用項の $p$ 値を比較しました(数値はすべて実測。 群分けは教材用の例示)。
| 対比(処置群 vs 対照群) | 処置群 傾き/年 | 対照群 傾き/年 | 差 | 交互作用 p | 平行性 |
|---|---|---|---|---|---|
| 三大都市圏8県 vs 残り39県 | +0.169% | -0.544% | 0.713 pt | <0.001 | ✗ 明確に違反 |
| 東北6県 vs 中国5県 | -0.843% | -0.511% | 0.332 pt | <0.001 | ✗ 違反 |
| 中位傾きで揃えた10県 vs 10県 | -0.499% | -0.475% | 0.024 pt | 0.231 | ○ 棄却されず |
読み取り。 経済構造が違う群(都市圏 vs 地方、 東北 vs 中国)を機械的にぶつけると、 処置前トレンドはそもそも平行でない(差 0.3〜0.7 ポイント/年、 $p<0.001$)。 一方、 処置前の傾きが近い都道府県どうしをマッチングして群を作ると、 傾き差は 0.024 ポイント/年まで縮まり、 交互作用は非有意($p=0.231$)になります。 同じデータでも「誰を対照にするか」で平行トレンドの成否が反転するという、 落とし穴③の生きた実例です。
同時に検出力(落とし穴⑥)の注意も見えます。 47都道府県 × 8年という比較的大きなパネルでは、 わずか 0.3 ポイント/年の傾き差でも $p<0.001$ になります。 逆に、 マッチング後に「$p=0.231$ だから平行」と早合点するのも禁物で、 非有意は「違反を検出できなかった」以上を意味しません。 傾き差の大きさ(0.024 pt/年は実務的に無視できる水準か)まで含めて判断してください。 なお、 ここで対数を用いたのは落とし穴⑤への配慮です。 水準(人)のままだと都市部の大きな値に検定が支配され、 別の結論になり得ます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import pandas as pd, numpy as np import statsmodels.formula.api as smf # SSDSE-B-2026: cp932 / 2行目の英語ヘッダをskip df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df.rename(columns={'SSDSE-B-2026': 'Year'}) pre = df[(df['Year'] >= 2012) & (df['Year'] <= 2019)].copy() pre['logpop'] = np.log(pre['A1101']) pre['yearc'] = pre['Year'] - 2012 # 三大都市圏を処置群に見立てた例(傾きが全く違う=前平行が破れる) T = ['埼玉県','千葉県','東京都','神奈川県','愛知県','大阪府','京都府','兵庫県'] pre['grp'] = pre['Prefecture'].isin(T).astype(int) # 県固定効果 + 年次×群 の交互作用が事前トレンド差の検定 m = smf.ols('logpop ~ yearc*grp + C(Prefecture)', data=pre).fit() print(m.params['yearc:grp'], m.pvalues['yearc:grp']) # 係数≈0.00713, p<0.001 |
※ 上記の傾き・p 値は SSDSE-B-2026 の実測値です。 処置群/対照群の分け方は概念説明のための架空の設定(実在の政策処置ではありません)。
平行トレンド仮定の前後にある概念へ、 本用語集内の実在ページへリンクします(未整備の項目はリンクせずテキストで示します)。