Install SyntheticControlMethods via pip
masterInstall the package using the standard Python package manager:
pip install SyntheticControlMethodsrepository·master·Indexed 41 days ago
https://github.com/oscarengelbrektson/syntheticcontrolmethodsA Python package for causal inference that implements Synthetic Control Methods (SCM) to estimate the effect of interventions on panel data or time-series. It provides the `Synth` class for ordinary and penalized synthetic controls, and the `DiffSynth` class for differenced synthetic controls. Features include validity testing via in-time and in-space placebo studies, and visualization tools for original, pointwise, and cumulative effects.
Install the package using the standard Python package manager:
pip install SyntheticControlMethodsThe SynthBase class acts as a central container for all variables, processed matrices, and results generated during the synthetic control procedure. It is used internally by Synth and DiffSynth to store state.
treated_outcome: (1 x pre-treatment periods) Outcome of the treated unit in the pre-treatment period.control_outcome: (n_controls x pre-treatment periods) Outcomes of all control units in the pre-treatment period.treated_covariates: (n_covariates x 1) Average value of each predictor for the treated unit in the pre-treatment period.control_covariates: (n_covariates x n_controls) Average value of each predictor for each control unit in the pre-treatment period.w: (1 x n_controls) The weights assigned to each control unit (must be non-negative and sum to 1).v: (n_covariates x n_covariates) A diagonal, positive semi-definite matrix representing the relative importance of each covariate.weight_df: A DataFrame containing the calculated unit weights.comparison_df: A DataFrame containing the comparison between the treated and synthetic units.Penalized Synthetic Controls attempt to make control units similar to the treated unit both before and after they are mixed into the synthetic unit. This helps mitigate bias if the relationship between outcome and covariates is non-linear.
By setting pen="auto", the penalization coefficient is optimized alongside the weights using pre-treatment data.
# Fit penalized synthetic control with automatic optimization
sc_pen = Synth(data, "gdp", "country", "year", 1990, "West Germany",
n_optim=30, pen="auto", exclude_columns=["code"])To use Synth or DiffSynth, your input dataset must follow these requirements:
ID: Unique identifier for the unit (e.g., string or integer).Time: Integer indicating the time period.outcome_var: The target variable being studied.covariates: Predictor variables used to match the treated unit.To evaluate the credibility of the synthetic control, perform placebo tests:
In-time Placebo: Reassigns the treatment to a different time period in the data. If the model shows a large effect in a period where no treatment occurred, the results are suspect.
sc.in_time_placebo(treatment_period, n_optim=...)In-space Placebo: Reassigns the treatment to different control units (the donor pool). A significant treatment effect is one where the treated unit's post-treatment RMSPE is unusually large compared to the distribution of placebo effects.
sc.in_space_placebo(n_placebos)# Run in-time placebo for the year 1982
sc.in_time_placebo(1982, n_optim=10)
sc.plot(['in-time placebo'])
# Run in-space placebo for 15 units
sc.in_space_placebo(15)
sc.plot(['rmspe ratio'])To use Synth or DiffSynth, your dataset must adhere to these formatting requirements:
country).code and country), drop one or use the exclude_columns argument.Synth() ignores them (using pre-treatment averages), while DiffSynth() automatically applies linear interpolation to impute them.The .plot() method generates three types of visualizations to analyze the intervention's impact:
"original": Shows the observed data for the treated unit alongside the counterfactual prediction (the synthetic control) for the post-treatment period."pointwise": Shows the difference between the observed data and the counterfactual predictions. This represents the estimated pointwise causal effect."cumulative": Shows the running sum of the pointwise contributions, representing the cumulative effect of the intervention over time.sc.plot(["original", "pointwise", "cumulative"],
treated_label="West Germany",
synth_label="Synthetic West Germany",
treatment_label="German Reunification")The Synth class is the primary interface for estimating causal effects using the synthetic control method. It requires a pandas DataFrame containing your panel data.
Parameters for Synth():
data: A pandas.DataFrame containing the observations.outcome_col: The name of the column representing the outcome of interest.unit_col: The name of the column representing the unit ID (e.g., 'country').time_col: The name of the column representing the time period (e.g., 'year').treatment_year: The year/period when the intervention occurred.treated_unit: The identifier for the unit that received the treatment.pen: Penalty parameter (default is 0).Methods:
plot(types, ...): Visualizes the results. types can be a list containing "original", "pointwise", and "cumulative".import pandas as pd
from SyntheticControlMethods import Synth
# Load your data
data = pd.read_csv("your_data.csv")
# Initialize and fit the model
sc = Synth(data, "outcome_column", "unit_column", "time_column", 1990, "Treated Unit Name", pen=0)
# Visualize the results
sc.plot(["original", "pointwise", "cumulative"],
treated_label="Treated Unit",
synth_label="Synthetic Unit",
treatment_label="Intervention Name")The DiffSynth() class implements Differenced Synthetic Controls. This method is useful if the ordinary Synth() fails (e.g., if the treated unit's outcome is more extreme than any control unit) because it focuses on matching the change in the outcome rather than the absolute level.
Arguments:
Synth().not_diff_cols: A list of column names to omit from the first-differencing process. Use this for covariates with high missingness where differencing is not meaningful.Note on Interpretation: In the comparison_df attribute, DiffSynth displays the average change in covariate values instead of the absolute average values.
from SyntheticControlMethods import DiffSynth
# Fit differenced synthetic control
# We exclude certain columns from differencing due to high missingness
dsc = DiffSynth(
data,
"gdp",
"country",
"year",
1990,
"West Germany",
not_diff_cols=["schooling", "invest60"],
n_optim=100
)The Synth class implements the standard Synthetic Control Method (SCM). It estimates a synthetic version of a treated unit by assigning weights to control units to match the treated unit's pre-treatment characteristics.
dataset: A Pandas DataFrame containing the observations. The dataset must be sorted by ID and then by Time.outcome_var: Name of the outcome column (e.g., 'gdp').id_var: Name of the unit identifier column (e.g., 'country').time_var: Name of the time period column (e.g., 'year').treatment_period: The first time period after treatment occurred (the first period affected by the effect).treated_unit: The ID of the unit that received the treatment.n_optim: (int, default: 10) Number of different initialization values for optimization. Higher values increase the chance of finding a global optimum but increase runtime.pen: (float, default: 0) Penalization coefficient. Higher values increase the importance of minimizing the pairwise difference of individual control units from the treated unit.from SyntheticControlMethods.main import Synth
import pandas as pd
# Example setup
df = pd.read_csv('your_data.csv')
synth = Synth(
dataset=df,
outcome_var='gdp',
id_var='country',
time_var='year',
treatment_period=1990,
treated_unit='West Germany',
n_optim=20,
pen=0.1
)The DiffSynth class implements the Differenced Synthetic Control Method (DSC). This method is useful when working with first-differences of variables to account for non-stationarity.
In addition to the standard Synth parameters, DiffSynth includes:
not_diff_cols: (list, default: []) A list of column names to omit from the first-differencing process. This is useful for columns where the first difference is not appropriate (e.g., if the proportion of missing values is high).DiffSynth automatically performs the following on the provided dataset:
from SyntheticControlMethods.main import DiffSynth
# Example setup for Differenced Synthetic Control
diff_synth = DiffSynth(
dataset=df,
outcome_var='gdp',
id_var='country',
time_var='year',
treatment_period=1990,
treated_unit='West Germany',
not_diff_cols=['some_stable_covariate']
)The Synth() class implements ordinary Synthetic Control methods. It attempts to find a weighted average of control units that closely resembles the treated unit in the pre-treatment period.
Arguments:
data: Pandas DataFrame (sorted by unit then time).outcome_var: Name of the outcome column (str).id_var: Name of the unit indicator column (str).time_var: Name of the time column (str).treatment_period: The first time point affected by treatment (int).treated_unit: The identifier of the unit that received treatment (str).n_optim: Number of initialization values for optimization (int, default: 10).pen: Penalization coefficient. 0 is classic SC; `