fast, scalable synthetic control methods. Full version powered by the pyensmallen
library for fast optimisation, and lean version powered by adelie
for blazing fast regression solvers.
Check out the notebooks
directory for synthetic and real data examples.
features are indicated by
- pending; good first PR; contributions welcome
- done
- unit weights [
/solvers.py
]- simplex (Abadie, Diamond, Hainmueller 2010, 2015)
- lasso (Hollingsworth and Wing 2024+)
- ridge (Imbens and Doudchenko 2016, Arkhangelsky et al 2021)
- matching (Imai, Kim, Wang 2023)
- support intercept term (Ferman and Pinto 2021, Doudchenko and Imbens)
- entropy weights (Hainmueller 2012, Hirschberg and Arkhangelsky 2023, Lal 2023)
- with multiple treated units, match aggregate outcomes (default) or individual outcomes (Abadie and L'Hour 2021)
- time weights
- L2 weights (Arkhangelsky et al 2021)
- time-distance penalised weights (Imbens et al 2024)
- augmenting weights with outcome models (Ben-Michael et al 2021)
- matrix completion (Athey et al 2021)
- latent factor models (Xu 2017, Lal et al 2024)
- two-way kernel ridge weights (Ben-Michael et al 2023)
- jacknife confidence intervals (multiple treated units) [Arkhangelsky et al 2021)
- permutation test (Abadie et al 2010)
- conformal inference (Chernozhukov et al 2021)
- raw outcome time series with treated average and synthetic control
- event study plot (treatment effect over time)
- weight distributions
Contributions welcome!
pip install git+https://github.com/apoorvalal/synthlearners/
or git clone and run uv pip install -e .
and make changes.
For fast, regularized synthetic control methods using adelie:
pip install synthlearners
This installs only the core dependencies:
numpy
,pandas
,matplotlib
- Basic data handling and plottingadelie
- Blazing fast regularized regression solver
Available methods:
PenguinSynth
- L1/L2 regularized synthetic control and SDID- All traditional CVX implementations (
adelie_synth
,synthetic_control
,synthetic_diff_in_diff
, etc.)
For all methods including traditional constrained optimization and matching:
pip install synthlearners[full]
For development, you would want to navigate to the repo location, and then run
uv pip install -e ".[full]"
which tells uv to install in editable mode with full
optional dependencies.
Additional dependencies:
scipy
,scikit-learn
- Optimization and cross-validationpyensmallen
- Frank-Wolfe optimizationfaiss-cpu
- Fast nearest neighbor searchjoblib
,tqdm
- Parallelization and progress barsseaborn
,ipywidgets
- Enhanced plotting and notebook widgets
Additional methods:
Synth
- Traditional synthetic control with various solversMatrixCompletionEstimator
- Matrix completion methods- Advanced cross-validation and inference tools
from synthlearners import PenguinSynth
# Ridge regularized synthetic control
estimator = PenguinSynth(method="synth", l1_ratio=0.0)
result = estimator.fit(df, "unit", "time", "treat", "outcome")
print(f"Treatment effect: {result.att:.3f}")
from synthlearners import Synth, PenguinSynth
# Traditional simplex-constrained synthetic control
synth = Synth(method="simplex")
result = synth.fit(Y, treated_units=15, T_pre=10)
# Or use the fast regularized version
penguin = PenguinSynth(method="synth", l1_ratio=0.5)
result = penguin.fit(df, "unit", "time", "treat", "outcome")
PenguinSynth (adelie): ~100x faster, no convergence issues, flexible regularization Traditional Synth: Full inference support, established methodology, more solvers