Skip to content
Scenario13 min read

Synthetic Control Method

Automated conversion of synthetic_control.ipynb

Synthetic Control Method

Data

Result

Ground-truth ATTE is 1.919269

Result
unit_idcalendar_timetreated_timeyy_cftau_realized_truemu_cfmu_treatedtau_mean_true
0donor_12000-0109.9716119.9716110.010.05908110.0590810.0
1donor_12000-02010.34437910.3443790.010.09746710.0974670.0
2donor_12000-03010.99849810.9984980.011.35409811.3540980.0
3donor_12000-04011.50871711.5087170.011.27771611.2777160.0
4donor_12000-05011.12528111.1252810.010.09879110.0987910.0

EDA

Result

PanelDataSCM(df=(1763, 4), y='y', unit_col='unit_id', time_col='calendar_time', treated_time='treated_time', time_freq='M', treated_unit='treated', treatment_start=Period('2003-02', 'M'), last_post_period=Period('2003-07', 'M'), n_pre_periods=37, n_post_periods=6, donor_units=['donor_1', 'donor_10', 'donor_11', 'donor_12', 'donor_13', 'donor_14', 'donor_15', 'donor_16', 'donor_17', 'donor_18', 'donor_19', 'donor_2', 'donor_20', 'donor_21', 'donor_22', 'donor_23', 'donor_24', 'donor_25', 'donor_26', 'donor_27', 'donor_28', 'donor_29', 'donor_3', 'donor_30', 'donor_31', 'donor_32', 'donor_33', 'donor_34', 'donor_35', 'donor_36', 'donor_37', 'donor_38', 'donor_39', 'donor_4', 'donor_40', 'donor_5', 'donor_6', 'donor_7', 'donor_8', 'donor_9'])

Result
donorpre_meanpre_stdpre_slopecorr_with_treated_prermse_to_treated_prermse_to_treated_pre_standardizedmean_diff_preslope_diff_premax_abs_gap_preis_never_treatedn_missing_precorr_rankstd_rmse_rankslope_rankcomposite_similarity_scorerank_by_similaritynotes
0donor_2020.7568774.2352560.0656720.6992983.0505741.1772420.0558000.0010457.515230True06210.9500001high_std_rmse
1donor_2318.8599823.4591600.1093250.7928792.8028491.081642-1.8410960.0446986.193337True011190.8500002high_std_rmse
2donor_1727.3743995.0042510.0621590.6949457.6332942.9457516.673322-0.00246715.022205True072330.7500003high_std_rmse
3donor_3512.8901962.4784840.0548960.7743417.9950723.085364-7.810882-0.00973011.244939True022570.7416674high_std_rmse
4donor_2712.1380522.5617730.0657320.7101078.7849343.390178-8.5630250.00110612.226100True042920.7333335high_std_rmse
5donor_3915.9332353.4934790.1016010.7560995.2879262.040654-4.7678430.0369749.398086True0316160.7333336high_std_rmse
6donor_222.0239103.7529400.0255930.5997733.2990441.2731281.322833-0.0390338.913091True0194170.6916677high_std_rmse
7donor_3423.2252664.2589880.1167990.6853024.0123471.5483982.5241890.0521738.782578True0811210.6916678high_std_rmse
8donor_2615.5315482.3672400.0585690.5843825.6456362.178697-5.169529-0.00605710.132082True0211850.6583339high_std_rmse
9donor_920.1983463.8946960.1851730.6098193.1348431.209762-0.5027310.12054610.776096True0153310.61666710high_std_rmse
10donor_3115.9745053.8091540.0465190.5732215.6788052.191497-4.726572-0.01810712.461670True0221990.60833311high_std_rmse
11donor_322.9844704.6788130.1623310.6395624.2792101.6513822.2833920.09770412.714594True01213260.60000012high_std_rmse
12donor_719.8880003.5650320.0488460.4348703.4714051.339644-0.813077-0.0157808.749577True037680.60000013high_std_rmse
13donor_3322.4674013.8903760.0616340.4372674.0191361.5510181.766323-0.0029939.071825True0361240.59166714high_std_rmse
14donor_610.8170571.6194710.0302230.70590410.0551803.880377-9.884020-0.03440415.388984True0533140.59166715high_std_rmse
15donor_2121.0015404.037106-0.0182810.5420383.4296401.3235260.300463-0.08290810.637405True0275250.55000016high_std_rmse
16donor_1328.4006645.2926880.0372270.6052908.7981813.3952907.699587-0.02739917.004455True01830120.52500017high_std_rmse
17donor_1521.6477894.2108290.1821640.5542893.6394931.4045100.9467120.11753713.105415True0247290.52500018high_std_rmse
18donor_129.9649961.8943910.0900930.60725310.9364094.220450-10.7360820.02546614.965497True01734100.51666719high_std_rmse
19donor_88.7722322.0987240.1042140.64746512.0985294.668922-11.9288450.03958817.063234True01035180.50000020high_std_rmse
20donor_3023.6849354.3569770.1161760.4976464.8336741.8653552.9838580.05154910.057305True03015200.48333321high_std_rmse
21donor_421.8015734.2072430.1795670.5245233.7669451.4536951.1004960.1149418.288093True0289280.48333322high_std_rmse
22donor_1022.1404684.5088050.2246460.5587794.0073461.5464681.4393910.1600199.740145True02310330.47500023high_std_rmse
23donor_525.4123614.3742730.0572710.3238306.3799702.4620834.711284-0.00735514.186181True0402160.46666724high_std_rmse
24donor_1815.3755112.8942780.1425640.5513535.9315332.289027-5.3255660.07793811.432539True02520230.45833325high_std_rmse
25donor_2525.6381454.7196780.1000070.4910596.4306632.4816464.9370680.03538113.366836True03322150.44166726high_std_rmse
26donor_3617.5568153.5104830.1320700.4902824.4726711.726041-3.1442620.06744410.183903True03414220.44166727high_std_rmse
27donor_111.4423752.5254620.1460530.6085119.5316243.678332-9.2587020.08142714.575727True01631240.43333328high_std_rmse
28donor_4011.3637761.9580710.0904760.5067759.6224393.713378-9.3373010.02585014.358223True02932110.42500029high_std_rmse
29donor_3218.8750093.180241-0.0495270.4047013.6732851.417551-1.826069-0.1141539.321772True0388270.41666730high_std_rmse
30donor_2827.8215625.5995060.3365260.6450328.3696953.2299347.1204840.27189916.331011True01126370.40833331high_std_rmse
31donor_1626.2305995.7609590.0959070.3709337.7074162.9743555.5295220.03128118.330394True03924130.39166732high_std_rmse
32donor_1131.8983845.7483970.2780220.62721112.1017754.67017411.1973070.21339524.414887True01336350.32500033high_std_rmse
33donor_3823.3412295.6078840.3270230.4731255.6020502.1618772.6401520.26239613.541965True03517360.29166734high_std_rmse
34donor_1964.64207413.2858800.4161000.66600345.47727917.55005643.9409970.35147487.274045True0940400.28333335high_std_rmse
35donor_2932.0691726.6803890.3926420.62357612.6089944.86591411.3680950.32801520.594296True01437380.28333336high_std_rmse
36donor_2412.6046433.1692440.1990550.4934368.6143213.324337-8.0964340.13442814.907594True03128320.26666737high_std_rmse
37donor_1427.3422676.2862050.3931000.5474358.5147983.2859316.6411900.32847315.190467True02627390.25833338high_std_rmse
38donor_3734.4057317.6634630.2318760.59056415.1593495.85011713.7046540.16724933.571787True02039340.25000039high_std_rmse
39donor_2234.3533515.2355900.1835910.49225814.3928435.55431613.6522740.11896427.762663True03238300.19166740high_std_rmse
Result

png

Inference

Result
value
field
estimandaverage_post_effect
modelAugmentedSyntheticControl
inferenceaverage_att_ttest
value3.9456 (ci_abs: 0.3664, 7.5249)
value_relative16.0707 (ci_rel: 1.4922, 30.6491)
alpha0.0500
p_value0.0417
is_significantTrue
post_outcome_d_mean28.3185
pointwise_post_period_average3.7668
effect_by_time[{'period': 2003-02, 'estimate': 3.32949405792...
cumulative_effect22.6007
n_significant_periods0
n_donors40
n_pre_periods37
n_post_periods6
time2026-04-01

So the avarage effect per period is 3.9456 with (ci_abs: 0.3664, 7.5249)

Refutation

Result

png

Result

png

As we see synthetic prediction of treated unit is close to real behavior before the intervention and has a gap after it

Placebo

Result
placebo_treatment_startn_pre_before_placebon_post_after_placeboaverage_att_placeboci_lowerci_upperp_valuerejects_zeropre_fit_metric
02000-03261.882234-16.33175620.0962230.414358False3.892700e-09
12000-04361.269647-2.9228105.4621050.322397False4.675707e-08
22000-05461.558211-2.7821125.8985340.262430False7.740750e-09
32000-06561.314722-2.9452655.5747090.315493False8.664180e-09
42000-07661.415188-1.5846804.4150560.179511False8.107963e-09
52000-08761.303852-3.1035015.7112040.331010False6.429904e-04
62000-09860.780444-2.0484303.6093180.357094False1.040816e-03
72000-10960.096428-5.8402396.0330950.950643False9.916453e-04
82000-11106-0.153322-5.2988974.9922530.909715False9.340734e-04
92000-12116-0.446809-6.7340405.8404220.788669False8.344978e-04
102001-01126-0.533169-8.2010657.1347260.793032False8.445828e-04
112001-02136-1.000896-6.3242114.3224200.503460False1.652109e-03
122001-03146-1.029470-4.5740492.5151090.337841False1.603717e-03
132001-04156-2.038412-5.3294561.2526310.116670False2.599095e-03
142001-05166-2.044195-6.0307901.9424000.158111False2.932379e-03
152001-06176-1.036773-5.8472383.7736920.451654False3.083936e-03
162001-071860.083509-4.8605375.0275550.948678False1.392011e-02
172001-08196-0.009216-4.4015694.3831370.993616False1.370060e-02
182001-09206-0.293440-1.4123070.8254260.376294False1.695760e-02
192001-10216-0.446168-3.0577482.1654120.538804False1.588256e-02
202001-11226-0.856900-4.0222052.3084050.364243False1.628196e-02
212001-12236-0.674266-3.9302972.5817650.466942False1.626443e-02
222002-01246-0.742673-1.6651300.1797840.074181False1.561529e-02
232002-02256-0.703350-2.4208451.0141440.220123False1.549205e-02
242002-03266-1.016980-5.8862213.8522600.463681False1.542201e-02
252002-04276-0.813858-3.7681262.1404100.357641False1.574491e-02
262002-05286-0.321246-2.7823372.1398440.630910False1.451867e-02
272002-06296-0.522664-4.0264182.9810900.586724False2.973806e-02
282002-07306-0.305588-5.2611134.6499380.815602False3.467258e-02
292002-08316-0.049686-4.8700994.7707270.968656False3.722547e-02

We pretend treatment has happened earlier.

  • placebo_treatment_start - where treatment starts
  • n_pre_before_placebo - how many periods were fitted before the treatment
  • n_post_after_placebo - how many periods were fitted after the treatment
  • average_att_placebo - average_post_effect
  • rejects_zero - p_value < alpha

So weak robustness when we have many rows have rejects_zero = false and average_att_placebo is small

Result
unit_idpre_rmsepost_rmsepost_pre_rmspe_ratioaverage_post_gapmax_abs_post_gaprank_post_pre_rmspe_ratiois_actual_treated
0donor_360.1261845.36169042.491118-3.6451568.6860131False
1donor_10.0907223.68557540.625069-1.7023215.1490122False
2donor_90.2707379.59048535.423589-4.57977417.0295183False
3treated0.1597915.31248833.2463761.5360049.7085604True
4donor_110.46531014.62446831.42952310.64543820.0235465False
5donor_350.3259949.95557430.539167-5.31753016.7176926False
6donor_100.40107012.22104930.471133-7.28139019.7698557False
7donor_230.3035999.20564530.3217063.99089717.3037718False
8donor_240.1355874.09819430.2255763.0951156.1440109False
9donor_80.0588171.74860329.7296960.1463093.26027610False
10donor_260.2938408.65732729.462709-6.53975216.29935811False
11donor_120.2015325.93231529.4360274.10774010.40821912False
12donor_30.61153116.76380527.41283611.52999332.13789813False
13donor_400.2945637.69660526.128854-1.39950811.97007214False
14donor_200.2395336.23627526.035093-4.7256268.66192515False
15donor_180.2873757.39252725.7242981.91877312.70240316False
16donor_310.2967977.44374125.080284-0.2813088.85594517False
17donor_290.63182115.83407225.061005-10.90197729.84462918False
18donor_380.50730812.11463423.8802361.31446417.03349819False
19donor_191.34158030.76777722.93399416.59120560.76077120False
20donor_270.2116284.64390521.9437663.5753786.70798321False
21donor_250.3505747.59476721.6637873.17853113.49302122False
22donor_130.3484926.62449519.0090490.99522412.01715223False
23donor_60.2828105.09555818.017589-2.3751508.36842524False
24donor_20.85479015.30815917.9086879.91679325.06351325False
25donor_170.69994811.92823117.041598-8.29353820.48332926False
26donor_40.6047849.93273116.4235965.89592715.13091327False
27donor_330.94659815.17692716.0331329.92525425.67744328False
28donor_210.5155428.10876015.7286182.16265214.01776329False
29donor_340.3707645.52949314.9137971.7314949.65210730False
30donor_50.5786148.31471414.370061-2.72446412.56995231False
31donor_140.5408237.76269514.353496-2.02410713.24524832False
32donor_220.78219510.47724113.394660-2.21662919.11979333False
33donor_150.5044066.70206513.2870353.53267911.58946434False
34donor_160.91493111.64065712.722994-0.76730918.66523135False
35donor_300.5937337.44893512.5459262.30239711.13576236False
36donor_370.99014312.32151212.444172-3.33559521.45801237False
37donor_320.5886096.89964911.7219502.44045712.72585238False
38donor_280.6909997.84949811.359643-0.1099268.85153139False
39donor_390.3945303.7149049.4160210.5267355.72774040False
40donor_70.8206267.1016918.6539904.79700711.59382141False

How to read columns:

  • unit_id: unit used as treated in that placebo run.
  • pre_rmse: pre-treatment fit error (lower is better).
  • post_rmse: post-treatment fit error.
  • post_pre_rmspe_ratio: post_rmse / pre_rmse (main Abadie-style statistic).
  • average_post_gap: mean post-treatment gap (observed - synthetic).
  • max_abs_post_gap: largest absolute post gap.
  • rank_post_pre_rmspe_ratio: rank of ratio, descending (1 = largest ratio).
  • is_actual_treated: True for your real treated unit.

Interpretation: You want the real treated unit (is_actual_treated=True) to have one of the largest post_pre_rmspe_ratio values (ideally rank near 1). If many placebo units have similar/larger ratios, treatment effect is less convincing. Also check pre_rmse: if pre-fit is poor for some placebos, their high ratios are less informative.

Sensitivity

Result
dropped_donoraverage_att_reestimateddelta_vs_full_modelpre_rmse_reestimatedmax_weight_after_refiteffective_n_donors_after_refit
0donor_14.2078580.2622230.1714050.3030300.946472
1donor_104.5877950.6421610.1608020.3491880.909245
2donor_114.1891360.2435020.1601200.3532470.909496
3donor_124.9162550.9706210.1891670.3364270.978294
4donor_134.4681270.5224920.1625250.3417350.927949
5donor_144.7250720.7794380.1601800.3588320.910183
6donor_154.5130500.5674160.1697110.3919100.908753
7donor_164.3820220.4363870.1593570.3528350.903756
8donor_173.622184-0.3234510.1588090.3564430.899310
9donor_184.4363930.4907590.1987040.3680781.149355
10donor_195.0473811.1017460.2199170.5108890.814392
11donor_25.2945681.3489330.2022150.5187480.700821
12donor_204.7665930.8209590.1600170.3540660.910676
13donor_214.8819310.9362970.1747640.3911850.830214
14donor_224.5535130.6078780.1899700.3973341.012346
15donor_235.0311141.0854800.2055740.4106200.976600
16donor_244.7020590.7564240.1609430.3479640.912077
17donor_254.5806270.6349930.1793220.4312340.862914
18donor_264.6009800.6553460.1579750.3410590.851219
19donor_274.5749780.6293440.1608450.3575050.843273
20donor_284.4519340.5063000.1742010.3438021.016530
21donor_295.1150171.1693820.1765270.3769090.909911
22donor_35.5890951.6434610.2909840.4691151.061081
23donor_304.6355300.6898950.1989090.3555220.836912
24donor_315.1944911.2488560.2533200.3150681.168234
25donor_325.5940681.6484340.2558860.9014560.421563
26donor_334.6371010.6914660.1908200.3424091.021246
27donor_345.5079401.5623060.2451730.7722100.663935
28donor_354.5821420.6365070.2268840.3195201.592468
29donor_364.9437010.9980670.2003680.3215390.956473
30donor_374.6260430.6804080.1527580.3414410.787437
31donor_383.669948-0.2756870.1839820.3562371.093042
32donor_395.1281411.1825070.1714800.4225000.764932
33donor_44.8094700.8638360.1673480.3613950.942294
34donor_404.7833460.8377110.1780370.3472511.081478
35donor_55.2011861.2555520.1666450.4544210.706770
36donor_64.5644040.6187700.1586560.3557880.894601
37donor_74.7188420.7732080.1846850.3291641.003481
38donor_84.5173870.5717530.1622230.3978540.872781
39donor_94.7656660.8200320.2113210.3956261.133550
  • dropped_donor: donor unit removed in that refit.
  • average_att_reestimated: ATT after removing that donor.
  • delta_vs_full_model: reestimated_ATT - original_full_model_ATT. Near 0 → estimate is stable to that donor. Large |deltal → that donor is influential.
  • pre_rmse_reestimated: pre-treatment fit error after refit. Higher than baseline → worse pre-fit when donor is removed.
  • max_weight_afterrefit: largest donor weight in refit.Very high (close to 1) → dependence on one donor.
  • effective_n_donors_after_refit: effective donor count (1 / sum (w^2)). Lower → concentration on fewer donors.

Model

Result
testflagvaluethresholdmessage
0pre_rmse_augmentedGREEN0.366248<= 0.5254Pre-treatment RMSE is within tolerance.
1max_abs_pre_gap_augmentedGREEN0.988290<= 1.314Largest pre-treatment gap is within tolerance.
2mean_gap_last_k_pre_augmentedGREEN0.207285<= 0.6568Average gap in the last 3 pre periods is cente...
3max_abs_weight_augmentedGREEN0.201943<= 2No extreme augmented donor weight detected (mo...
4l1_norm_weights_augmentedGREEN2.245170<= 5Total absolute augmented weight mass is contro...
5negative_weight_shareGREEN0.277300<= 0.3Negative-weight share is moderate.
6slsqp_fallback_countGREEN0.000000== 0No optimizer fallback events recorded.
7suppressed_fit_warning_countGREEN0.000000== 0No suppressed fit warnings were captured.

We can call our estimate robust