Synthetic Difference-in-Differences (SDID) for causal inference in Python
Reason this release was yanked:
Buggy SDID estimator (degenerate time weights). Upgrade to 0.4.0.
Project description
Synthetic Difference-in-Differences (SDID)
English
A Python implementation of Synthetic Difference-in-Differences for causal inference.
Overview
SDID combines synthetic control methods with difference-in-differences to provide robust causal effect estimates. It automatically finds optimal weights for:
- Control units: Creates a synthetic comparison group
- Time periods: Balances pre/post treatment comparisons
Installation
From PyPI (Recommended)
pip install sdid
From Source
git clone https://github.com/yourusername/sdid.git
cd sdid
pip install .
Development Installation
git clone https://github.com/yourusername/sdid.git
cd sdid
uv sync --extra dev
Quick Start
import pandas as pd
from sdid import SyntheticDiffInDiff
# Load your panel data
data = pd.read_csv("your_data.csv")
# Initialize and fit
sdid = SyntheticDiffInDiff(
data=data,
outcome_col="outcome",
times_col="year",
units_col="state",
treat_col="treated",
post_col="post"
)
# Estimate treatment effect
effect = sdid.fit()
print(f"Treatment Effect: {effect:.4f}")
# Estimate standard error
sdid.estimate_se(n_bootstrap=200, n_jobs=4)
print(sdid.summary())
Data Format
Your data should be in long format (one row per unit-time observation):
| Column | Description | Example |
|---|---|---|
outcome |
Outcome variable | Sales, GDP |
times |
Time period | 2018, 2019, 2020 |
units |
Unit identifier | "CA", "TX", "NY" |
treat |
Treatment indicator | 0 = control, 1 = treated |
post |
Post-treatment period | 0 = before, 1 = after |
Example:
unit year outcome treated post
CA 2018 100.5 0 0
CA 2019 102.3 0 0
CA 2020 105.1 0 1
TX 2018 98.2 1 0
TX 2019 99.8 1 0
TX 2020 108.7 1 1
API Reference
| Method | Description |
|---|---|
fit(verbose=False) |
Fit model and return treatment effect |
estimate_se(n_bootstrap, seed, n_jobs) |
Estimate standard error via placebo bootstrap |
summary() |
Return formatted results summary |
run_event_study(times) |
Estimate effects for multiple periods |
plot_event_study(times, ...) |
Create event study plot with confidence intervals |
get_weights_summary() |
Return unit and time weights |
is_fitted |
Property to check if model is fitted |
Event Study
# Estimate dynamic treatment effects
effects = sdid.run_event_study([2020, 2021, 2022])
# Plot with confidence intervals
fig = sdid.plot_event_study(
times=[2020, 2021, 2022],
n_bootstrap=200,
confidence_level=0.95,
n_jobs=4
)
fig.savefig("event_study.png", dpi=300)
Assumptions
SDID relies on these key assumptions:
- No anticipation: Units don't change behavior before treatment
- SUTVA: No spillover effects between units
- Overlap: Control units can approximate treated units
Reference
@article{arkhangelsky2021synthetic,
title={Synthetic difference-in-differences},
author={Arkhangelsky, Dmitry and Athey, Susan and Hirshberg, David A and Imbens, Guido W and Wager, Stefan},
journal={American Economic Review},
volume={111},
number={12},
pages={4088--4118},
year={2021}
}
Development
# Install dev dependencies
uv sync --extra dev
# Run tests
uv run pytest tests/ -v
# Run linter
uv run ruff check .
# Format code
uv run ruff format .
# Build package
uv build
# Upload to PyPI (requires API token)
uv publish
License
MIT License - see LICENSE for details.
繁體中文
合成雙重差分法 (SDID) 的 Python 實現,用於因果推論。
概述
SDID 結合了合成控制法與雙重差分法的優點,提供穩健的因果效應估計。它自動計算最佳權重:
- 控制單位權重:建立合成對照組
- 時間期間權重:平衡處理前後的比較
安裝
從 PyPI 安裝(推薦)
pip install sdid
從原始碼安裝
git clone https://github.com/yourusername/sdid.git
cd sdid
pip install .
開發安裝
git clone https://github.com/yourusername/sdid.git
cd sdid
uv sync --extra dev
快速開始
import pandas as pd
from sdid import SyntheticDiffInDiff
# 載入面板資料
data = pd.read_csv("your_data.csv")
# 初始化並擬合
sdid = SyntheticDiffInDiff(
data=data,
outcome_col="outcome", # 結果變數
times_col="year", # 時間
units_col="state", # 單位識別
treat_col="treated", # 處理指標
post_col="post" # 處理後指標
)
# 估計處理效果
effect = sdid.fit()
print(f"處理效果: {effect:.4f}")
# 估計標準誤
sdid.estimate_se(n_bootstrap=200, n_jobs=4)
print(sdid.summary())
資料格式
資料須為長格式(每個單位-時間組合一列):
| 欄位 | 說明 | 範例 |
|---|---|---|
outcome |
結果變數 | 銷售額、GDP |
times |
時間期間 | 2018, 2019, 2020 |
units |
單位識別 | "CA", "TX", "NY" |
treat |
處理指標 | 0 = 控制組, 1 = 處理組 |
post |
處理後期間 | 0 = 處理前, 1 = 處理後 |
範例:
unit year outcome treated post
CA 2018 100.5 0 0
CA 2019 102.3 0 0
CA 2020 105.1 0 1
TX 2018 98.2 1 0
TX 2019 99.8 1 0
TX 2020 108.7 1 1
API 參考
| 方法 | 說明 |
|---|---|
fit(verbose=False) |
擬合模型並回傳處理效果 |
estimate_se(n_bootstrap, seed, n_jobs) |
透過安慰劑 bootstrap 估計標準誤 |
summary() |
回傳格式化的結果摘要 |
run_event_study(times) |
估計多個時間點的效果 |
plot_event_study(times, ...) |
繪製帶信賴區間的事件研究圖 |
get_weights_summary() |
回傳單位和時間權重 |
is_fitted |
檢查模型是否已擬合的屬性 |
事件研究
# 估計動態處理效果
effects = sdid.run_event_study([2020, 2021, 2022])
# 繪製帶信賴區間的圖表
fig = sdid.plot_event_study(
times=[2020, 2021, 2022],
n_bootstrap=200,
confidence_level=0.95,
n_jobs=4
)
fig.savefig("event_study.png", dpi=300)
假設條件
SDID 依賴以下關鍵假設:
- 無預期效應:單位不會在處理前改變行為
- SUTVA:單位間無外溢效應
- 重疊性:控制單位能近似處理單位
參考文獻
@article{arkhangelsky2021synthetic,
title={Synthetic difference-in-differences},
author={Arkhangelsky, Dmitry and Athey, Susan and Hirshberg, David A and Imbens, Guido W and Wager, Stefan},
journal={American Economic Review},
volume={111},
number={12},
pages={4088--4118},
year={2021}
}
開發
# 安裝開發相依套件
uv sync --extra dev
# 執行測試
uv run pytest tests/ -v
# 執行 linter
uv run ruff check .
# 格式化程式碼
uv run ruff format .
# 建置套件
uv build
# 上傳到 PyPI(需要 API token)
uv publish
授權
MIT 授權 - 詳見 LICENSE。
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sdid-0.2.0.tar.gz.
File metadata
- Download URL: sdid-0.2.0.tar.gz
- Upload date:
- Size: 16.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.22
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
62c81c8d664635fc1bd52f78ffc2db80d760630fa11759b0fe4ef5ebc92fe29b
|
|
| MD5 |
6b008d53aece9a8e2c284da937d39598
|
|
| BLAKE2b-256 |
d54cd65a71a9146f6f407a07a042a7ead9f1ef7677358db9a1012501359e0202
|
File details
Details for the file sdid-0.2.0-py3-none-any.whl.
File metadata
- Download URL: sdid-0.2.0-py3-none-any.whl
- Upload date:
- Size: 13.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.22
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eae4c6f9bb3a9221087377beddb620252c08691041bb2eeed78b6602778a904f
|
|
| MD5 |
63e22271e3de8c7e3f4cd29afe9bf10b
|
|
| BLAKE2b-256 |
98dccc4919114f940da58d76dbcbcccb2b9f521f63fedc9ac5931f50bf45688c
|