pip install csdid+https://github.com/d2cml-ai/DRDID pip install git
csdid
Python package for doubly-robust and ipw DiD estimator (callaway and sant’anna 2021)
csdid is a package that implements the DiD estimators proposed by Callaway and Sant’Anna (2021) that solves the bias of the TWFE estimator in staggered DiD. Documentation can be found here.
Install the package by inputting the following into the terminal:
sample code
Start by loading packages and the data:
from csdid.att_gt import ATTgt
import pandas as pd
= pd.read_csv('df.csv') df
We first create the estimation object with the ATTgt()
function, then fit the model with the .fit()
method.
Note: id
variable should be transformed to an integer variable before starting. Set cohort = 0
for never-treated units.
= ATTgt(
csdid = "outcome",
yname = "cohort", # cohort = 0 for never-treated
gname = "id", # must be a integer-variable
idname = "time",
tname = f"outcome ~ covar", # (optional)
xformla = "notyettreated", # use "nevertreated" if large sample
control_group = df,
data
)
= csdid.fit(est_method = 'dr') # switch to ipw if issues mod
We use the aggte()
method to aggregate our matched treatment effects into an overall treatment effect.
= 'simple') mod.aggte(typec
#>
#>
#> ATT Std. Error [95.0% Conf. Int.]
#> -0.9761 0.5134 -1.9823 0.0301
#>
#>
#> ---
#> Signif. codes: `*' confidence band does not cover 0
#> Control Group: None ,
#> Anticipation Periods: 0
#> Estimation Method: Doubly Robust
#>
#>
#> <csdid.att_gt.ATTgt object at 0x176104e00>
We can estimate dynamic treatment effects with the .aggte()
method and plot with the .plot_aggte()
method.
= 'dynamic') mod.aggte(typec
#>
#>
#> Overall summary of ATT's based on event-study/dynamic aggregation:
#> ATT Std. Error [95.0% Conf. Int.]
#> 0.7669 0.2744 0.2292 1.3047 *
#>
#>
#> Dynamic Effects:
#> Event time Estimate Std. Error [95.0% Simult. Conf. Band
#> 0 -7 0.7884 0.4399 -0.0738 1.6506
#> 1 -6 -0.7444 0.5493 -1.8211 0.3323
#> 2 -5 0.0099 0.3481 -0.6723 0.6921
#> 3 -4 0.0249 0.2798 -0.5235 0.5733
#> 4 -3 0.1380 0.2909 -0.4322 0.7082
#> 5 -2 0.3772 0.3234 -0.2567 1.0111
#> 6 -1 -0.0628 0.2707 -0.5934 0.4678
#> 7 0 -4.8345 0.4002 -5.6189 -4.0500 *
#> 8 1 -3.5553 0.4325 -4.4030 -2.7077 *
#> 9 2 -2.0860 0.3683 -2.8079 -1.3641 *
#> 10 3 -0.3910 0.5866 -1.5408 0.7588
#> 11 4 0.8165 0.4939 -0.1516 1.7845
#> 12 5 1.9183 0.7950 0.3601 3.4764 *
#> 13 6 4.8726 0.3566 4.1735 5.5716 *
#> 14 7 4.5839 0.3666 3.8653 5.3025 *
#> 15 8 5.5782 0.7030 4.2004 6.9560 *
#> ---
#> Signif. codes: `*' confidence band does not cover 0
#> Control Group: None ,
#> Anticipation Periods: 0
#> Estimation Method: Doubly Robust
#>
#>
#> <csdid.att_gt.ATTgt object at 0x176104e00>
mod.plot_aggte()
We can also aggregate effects by initial treatment period group, and with the ggdid()
function:
= 'group') mod.aggte(typec
#>
#>
#> Overall summary of ATT's based on group/cohort aggregation:
#> ATT Std. Error [95.0% Conf. Int.]
#> -2.2754 0.1744 -2.6172 -1.9335 *
#>
#>
#> Group Effects:
#> Group Estimate Std. Error [95.0% Simult. Conf. Band
#> 0 2 2.0844 0.3088 1.4792 2.6896 *
#> 1 3 1.3054 0.4666 0.3909 2.2199 *
#> 2 4 1.1756 0.5939 0.0115 2.3396 *
#> 3 5 -2.9813 0.4090 -3.7829 -2.1798 *
#> 4 6 -2.8821 0.6780 -4.2109 -1.5533 *
#> 5 7 -4.5846 0.9108 -6.3697 -2.7995 *
#> 6 8 -5.1020 0.3623 -5.8120 -4.3919 *
#> 7 9 -7.2184 0.4083 -8.0186 -6.4182 *
#> ---
#> Signif. codes: `*' confidence band does not cover 0
#> Control Group: None ,
#> Anticipation Periods: 0
#> Estimation Method: Doubly Robust
#>
#>
#> <csdid.att_gt.ATTgt object at 0x176104e00>
mod.plot_aggte()