Skip to content

Borusyak, Jaravel, Spiess (2023), Gardner (2021), Sun & Abraham (2021) staggered difference in differences estimators in Julia

Notifications You must be signed in to change notification settings

eohne/StagDiDModels.jl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

StagDiDModels.jl

(Some) modern staggered difference-in-differences estimators for Julia.

Overview

StagDiDModels.jl implements some of the recent advances in difference-in-differences estimation that address heterogeneous treatment effects in staggered treatment adoption. All estimators provide standard errors, model diagnostics, and are compatible with the StatsAPI ecosystem.

Available Estimators

Estimator Function Reference
BJS Imputation fit_bjs() Borusyak, Jaravel, Spiess (2023)
Gardner Two-Stage fit_gardner2s_static(), fit_gardner_dynamic() Gardner (2021)
Sun-Abraham fit_sunab() Sun & Abraham (2021)
TWFE fit_twfe_static(), fit_twfe_dynamic() Standard approach

Installation

using Pkg
Pkg.add(url="https://github.com/eohne/StagDiDModels.jl")

using StagDiDModels
using DataFrames

Data Requirements

Panel data with the following variables:

  • Unit identifier (e.g., firm, individual)
  • Time period (integer, e.g., year, quarter)
  • Treatment timing (when unit first receives treatment)
  • Outcome variable

Never-treated units must be coded as g = 0 or g = missing.

Basic Usage

BJS Imputation Estimator

Static average treatment effect:

julia> fit_bjs_static(df; y=:dep_var, id=:unit, t=:year, g=:g,cluster=:unit)
                 BJSModel
==========================================
Number of obs: 31000  Outcome:    :dep_var
Treated obs:   10253  Est. Type:   :static
Donor obs:     20747  R² First Stage:0.777
Cluster:       :unit
==========================================
        Coef.  Std. Error      t  Pr(>|t|)
──────────────────────────────────────────
_ATT  2.26295   0.0313968  72.08    <1e-99
==========================================

Dynamic event study:

fit_bjs_dynamic(df; y=:dep_var, id=:unit, t=:year, g=:g,
                                      horizons=true, pretrends=true, cluster=:unit)
┌ Warning: Collinear pre-trends omitted: pre20
└ @ Main c:\Users\eohneberg\OneDrive\Julia\Packages\DiDModels.jl\src\estimators\bjs.jl:492
                    BJSModel
================================================
Number of obs:    31000  Outcome:       :dep_var
Treated obs:      10253  Est. Type:     :dynamic
Donor obs:        20747  R² First Stage:   0.777
Cluster:          :unit
================================================
              Coef.  Std. Error      t  Pr(>|t|)
────────────────────────────────────────────────
τ::-19   0.00494698   0.142763    0.03    0.9724
τ::-18  -0.094598     0.142099   -0.67    0.5057
τ::-17  -0.0812596    0.144141   -0.56    0.5731
τ::-16  -0.112528     0.13729    -0.82    0.4126
τ::-15  -0.0753304    0.14184    -0.53    0.5955
τ::-14   0.05654      0.144027    0.39    0.6947
τ::-13  -0.068671     0.143188   -0.48    0.6316
τ::-12  -0.0915126    0.14232    -0.64    0.5204
τ::-11  -0.243579     0.142098   -1.71    0.0868
τ::-10  -0.077792     0.106634   -0.73    0.4659
τ::-9   -0.052073     0.129615   -0.40    0.6880
τ::-8   -0.123991     0.128756   -0.96    0.3358
τ::-7   -0.00807412   0.129888   -0.06    0.9504
τ::-6   -0.242521     0.131568   -1.84    0.0656
τ::-5   -0.157734     0.130259   -1.21    0.2262
τ::-4   -0.0704127    0.126895   -0.55    0.5791
τ::-3   -0.105707     0.132233   -0.80    0.4242
τ::-2   -0.0469036    0.13182    -0.36    0.7221
τ::-1   -0.11832      0.128169   -0.92    0.3561
τ::0     1.51314      0.0754774  20.05    <1e-74
τ::1     1.66384      0.0767514  21.68    <1e-84
τ::2     1.86437      0.0745015  25.02    <1e-99
τ::3     1.91872      0.074717   25.68    <1e-99
τ::4     1.87322      0.0741817  25.25    <1e-99
τ::5     1.87845      0.0756719  24.82    <1e-99
τ::6     2.14373      0.0763269  28.09    <1e-99
τ::7     2.23778      0.0761084  29.40    <1e-99
τ::8     2.3365       0.0744627  31.38    <1e-99
τ::9     2.34353      0.0747168  31.37    <1e-99
τ::10    2.53443      0.0810955  31.25    <1e-99
τ::11    2.47945      0.119535   20.74    <1e-79
τ::12    2.63494      0.115318   22.85    <1e-92
τ::13    2.9445       0.110473   26.65    <1e-99
τ::14    2.78171      0.114664   24.26    <1e-99
τ::15    2.71471      0.120305   22.57    <1e-90
τ::16    2.88065      0.115632   24.91    <1e-99
τ::17    2.99384      0.114385   26.17    <1e-99
τ::18    2.64617      0.115458   22.92    <1e-93
τ::19    2.87531      0.114058   25.21    <1e-99
τ::20    2.90466      0.113202   25.66    <1e-99
================================================

General specification:

julia> model = fit_bjs(df; 
    y=:dep_var,                   # Outcome variable
    id=:unit,                     # Unit identifier  
    t=:year,                      # Time variable
    g=:g,                         # Treatment timing
    controls=Symbol[],            # Control variables
    fe=(:unit, :year),                   # Fixed effects (default: unit + time)
    weights=:w,                   # Observation weights
    cluster=:unit,                # Clustering variable
    horizons=[0,1,2,3,4],         # Post-treatment periods
    pretrends=[-3,-2,-1],         # Pre-treatment periods
)
                   BJSModel
===============================================
Number of obs:   31000   Outcome:      :dep_var
Treated obs:     10253   Est. Type:    :dynamic
Donor obs:       20747   R² First Stage:  0.780
Cluster:         :unit
===============================================
             Coef.  Std. Error      t  Pr(>|t|)
───────────────────────────────────────────────
τ::-3  -0.00691821   0.0829011  -0.08    0.9335
τ::-2   0.0415102    0.0828488   0.50    0.6165
τ::-1   0.0295101    0.0802191   0.37    0.7130
τ::0    1.53155      0.0828972  18.48    <1e-65
τ::1    1.61755      0.0845701  19.13    <1e-69
τ::2    1.86139      0.0822017  22.64    <1e-91
τ::3    1.97443      0.0811454  24.33    <1e-99
τ::4    1.82614      0.079427   22.99    <1e-93
===============================================

Gardner Two-Stage DiD

Static:

julia> fit_gardner_static(df; y=:dep_var, id=:unit, t=:year, g=:g,
                                cluster=:unit)
               GardnerModel
==========================================
Number of obs: 31000  R²:            0.353
Treated obs:   10253  R² adjusted:   0.353
Donor obs:     20747  F-statistic: 16904.0
Outcome:    :dep_var  Cluster :      :unit
==========================================
        Coef.  Std. Error      t  Pr(>|t|)
──────────────────────────────────────────
_ATT  2.26295   0.0338789  66.80    <1e-99
==========================================

Dynamic:

julia> fit_gardner_dynamic(df; y=:dep_var, id=:unit, t=:year, g=:g,
                                 cluster=:unit, ref_p=-1)
                  GardnerModel
=================================================
Number of obs:    31000   R²:               0.373
Treated obs:      10253   R² adjusted:      0.372
Donor obs:        20747   F-statistic:    460.171
Outcome:       :dep_var   Cluster :         :unit
=================================================
               Coef.  Std. Error      t  Pr(>|t|)
─────────────────────────────────────────────────
τ::-20   0.0482675     0.0604799   0.80    0.4248
τ::-19   0.0434281     0.0607702   0.71    0.4748
τ::-18  -0.000894858   0.0609516  -0.01    0.9883
τ::-17  -0.028753      0.0632599  -0.45    0.6495
τ::-16   0.0246948     0.0602951   0.41    0.6821
τ::-15   0.0228411     0.0612728   0.37    0.7093
τ::-14   0.0840854     0.064303    1.31    0.1910
τ::-13   0.0107916     0.0615972   0.18    0.8609
τ::-12  -0.023326      0.0637062  -0.37    0.7143
τ::-11  -0.10326       0.0639668  -1.61    0.1065
τ::-10  -0.00170496    0.0413833  -0.04    0.9671
τ::-9    0.0129794     0.0411607   0.32    0.7525
τ::-8   -0.0143057     0.0416646  -0.34    0.7313
τ::-7    0.0533169     0.0409899   1.30    0.1934
τ::-6   -0.082763      0.0412686  -2.01    0.0449
τ::-5   -0.0377117     0.0413368  -0.91    0.3616
τ::-4   -0.00635132    0.0407193  -0.16    0.8761
τ::-3   -0.00746851    0.0414751  -0.18    0.8571
τ::-2    0.0315947     0.0421007   0.75    0.4530
τ::0     1.51314       0.076538   19.77    <1e-85
τ::1     1.66384       0.0782553  21.26    <1e-98
τ::2     1.86437       0.0761971  24.47    <1e-99
τ::3     1.91872       0.0759098  25.28    <1e-99
τ::4     1.87322       0.0750175  24.97    <1e-99
τ::5     1.87845       0.0765166  24.55    <1e-99
τ::6     2.14373       0.0763666  28.07    <1e-99
τ::7     2.23778       0.0763247  29.32    <1e-99
τ::8     2.3365        0.0749124  31.19    <1e-99
τ::9     2.34353       0.0747161  31.37    <1e-99
τ::10    2.53443       0.0811948  31.21    <1e-99
τ::11    2.47945       0.119535   20.74    <1e-94
τ::12    2.63494       0.115318   22.85    <1e-99
τ::13    2.9445        0.110473   26.65    <1e-99
τ::14    2.78171       0.114664   24.26    <1e-99
τ::15    2.71471       0.120305   22.57    <1e-99
τ::16    2.88065       0.115632   24.91    <1e-99
τ::17    2.99384       0.114385   26.17    <1e-99
τ::18    2.64617       0.115458   22.92    <1e-99
τ::19    2.87531       0.114058   25.21    <1e-99
τ::20    2.90466       0.113202   25.66    <1e-99
=================================================

Sun-Abraham Estimator

ATT:

julia> fit_sunab(df; y=:dep_var, id=:unit, t=:year, g=:g,
                         cluster=:unit, agg=:att)
               SunabModel
=========================================
Number of obs:31000   R²:           0.799
Treated obs:  10253   R² adjusted:  0.792
Pre obs:      20747   F-statistic:1.23502e5
Dep. Var:  :dep_var   Cluster:      :unit
=========================================
       Coef.  Std. Error      t  Pr(>|t|)
─────────────────────────────────────────
ATT  2.32119   0.0820088  28.30    <1e-99
=========================================

Dynamic coefficients:

julia> fit_sunab(df; y=:dep_var, id=:unit, t=:year, g=:g,
                         cluster=:unit, agg=:dynamic)
                   SunabModel
=================================================
Number of obs:    31000   R²:               0.799
Treated obs:      10253   R² adjusted:      0.792
Pre obs:          20747   F-statistic:    3083.66
Dep. Var:      :dep_var   Cluster:          :unit
=================================================
               Coef.  Std. Error      t  Pr(>|t|)
─────────────────────────────────────────────────
τ::-20  -0.0151877     0.147769   -0.10    0.9182
τ::-19  -0.0082711     0.147491   -0.06    0.9553
τ::-18  -0.0997613     0.152664   -0.65    0.5136
τ::-17  -0.0760892     0.151675   -0.50    0.6160
τ::-16  -0.113553      0.152684   -0.74    0.4572
τ::-15  -0.121286      0.152397   -0.80    0.4263
τ::-14   0.000968567   0.150746    0.01    0.9949
τ::-13  -0.0875309     0.148901   -0.59    0.5568
τ::-12  -0.0281754     0.154189   -0.18    0.8550
τ::-11  -0.324711      0.152768   -2.13    0.0338
τ::-10   0.0398103     0.108042    0.37    0.7126
τ::-9    0.0655079     0.108619    0.60    0.5466
τ::-8   -0.00649778    0.107914   -0.06    0.9520
τ::-7    0.109307      0.108343    1.01    0.3133
τ::-6   -0.125073      0.108768   -1.15    0.2505
τ::-5   -0.039797      0.108363   -0.37    0.7135
τ::-4    0.0476292     0.10436     0.46    0.6482
τ::-3    0.0119353     0.103833    0.11    0.9085
τ::-2    0.0698439     0.109226    0.64    0.5227
τ::0     1.53545       0.109545   14.02    <1e-40
τ::1     1.69124       0.109982   15.38    <1e-47
τ::2     1.87083       0.106399   17.58    <1e-59
τ::3     1.9474        0.108805   17.90    <1e-61
τ::4     1.84971       0.106231   17.41    <1e-58
τ::5     1.89713       0.109857   17.27    <1e-57
τ::6     2.18776       0.107846   20.29    <1e-76
τ::7     2.25533       0.105809   21.32    <1e-82
τ::8     2.32726       0.108476   21.45    <1e-83
τ::9     2.3889        0.0952692  25.08    <1e-99
τ::10    2.55571       0.109845   23.27    <1e-95
τ::11    2.62696       0.161015   16.32    <1e-52
τ::12    2.78245       0.153434   18.13    <1e-63
τ::13    3.09201       0.153139   20.19    <1e-75
τ::14    2.92923       0.152714   19.18    <1e-69
τ::15    2.86222       0.158084   18.11    <1e-62
τ::16    3.02817       0.155266   19.50    <1e-71
τ::17    3.14135       0.152887   20.55    <1e-77
τ::18    2.79368       0.158095   17.67    <1e-60
τ::19    3.02282       0.153328   19.71    <1e-72
τ::20    3.05217       0.152721   19.99    <1e-74
=================================================

Two-Way Fixed Effects

Static:

julia> fit_twfe_static(df; y=:dep_var, id=:unit, t=:year, g=:g,
                               cluster=:unit)
                TWFEModel
==========================================
Number of obs: 31000  R²:            0.794
Post obs:      21320  R² adjusted:   0.787
Pre obs:        9680  F-statistic:119798.0
Dep. Var:   :dep_var  Cluster:       :unit
==========================================
        Coef.  Std. Error      t  Pr(>|t|)
──────────────────────────────────────────
post  2.01215   0.0311817  64.53    <1e-99
==========================================

Dynamic:

julia> fit_twfe_dynamic(df; y=:dep_var, id=:unit, t=:year, g=:g,
                                cluster=:unit, ref_p=-1)
                   TWFEModel
================================================
Number of obs:    31000  R²:               0.799
Post obs:         10253  R² adjusted:      0.792
Pre obs:          20747  F-statistic:    3073.42
Dep. Var:      :dep_var  Cluster:          :unit
================================================
              Coef.  Std. Error      t  Pr(>|t|)
────────────────────────────────────────────────
τ::-20   0.228396      0.121549   1.88    0.0605
τ::-19   0.225683      0.122522   1.84    0.0658
τ::-18   0.124711      0.127555   0.98    0.3285
τ::-17   0.143929      0.127102   1.13    0.2577
τ::-16   0.122706      0.123789   0.99    0.3218
τ::-15   0.159711      0.126671   1.26    0.2077
τ::-14   0.317349      0.126036   2.52    0.0120
τ::-13   0.181699      0.123417   1.47    0.1413
τ::-12   0.148058      0.127864   1.16    0.2472
τ::-11   0.0253997     0.104909   0.24    0.8087
τ::-10  -0.0456146     0.104611  -0.44    0.6629
τ::-9   -0.0361548     0.106546  -0.34    0.7344
τ::-8   -0.111102      0.105043  -1.06    0.2905
τ::-7    0.0172967     0.105776   0.16    0.8701
τ::-6   -0.195828      0.105384  -1.86    0.0634
τ::-5   -0.11145       0.105431  -1.06    0.2907
τ::-4    0.0305665     0.101692   0.30    0.7638
τ::-3   -0.0268863     0.10111   -0.27    0.7904
τ::-2    0.00899443    0.106906   0.08    0.9330
τ::0     1.47408       0.104917  14.05    <1e-40
τ::1     1.63928       0.107153  15.30    <1e-46
τ::2     1.82363       0.103913  17.55    <1e-59
τ::3     1.90212       0.106412  17.87    <1e-61
τ::4     1.79594       0.10399   17.27    <1e-57
τ::5     1.82125       0.107351  16.97    <1e-56
τ::6     2.09319       0.104439  20.04    <1e-74
τ::7     2.18456       0.103711  21.06    <1e-81
τ::8     2.30298       0.106062  21.71    <1e-85
τ::9     2.27728       0.091008  25.02    <1e-99
τ::10    2.55733       0.108288  23.62    <1e-97
τ::11    2.44798       0.136409  17.95    <1e-61
τ::12    2.6095        0.131919  19.78    <1e-73
τ::13    2.89423       0.130662  22.15    <1e-88
τ::14    2.68905       0.127594  21.08    <1e-81
τ::15    2.62285       0.135489  19.36    <1e-70
τ::16    2.68003       0.132898  20.17    <1e-75
τ::17    2.83728       0.128553  22.07    <1e-87
τ::18    2.5352        0.133589  18.98    <1e-68
τ::19    2.6402        0.125345  21.06    <1e-81
τ::20    2.76279       0.129787  21.29    <1e-82
================================================

Model Output

All models support standard StatsAPI functions:

coef(model)              # Coefficient estimates
vcov(model)              # Variance-covariance matrix
stderror(model)          # Standard errors
coefnames(model)         # Coefficient names
confint(model)           # Confidence intervals
nobs(model)              # Number of observations

Post-Estimation Analysis

Cumulative Effects

julia> model = fit_sunab(df; y=:dep_var, id=:unit, t=:year, g=:g,
                                cluster=:unit, agg=:dynamic);
julia> cum_effects = cumulative_effects(model);

# Access results
julia> cum_effects.τ           # Event times
40-element Vector{Int64}:
 -20
 -19
   
  19
  20

julia> cum_effects.cumulative  # Cumulative effects
40-element Vector{Float64}:
 -0.7009304415811053
 -0.6857427528313305
  
 48.78563490491884
 51.83780653599853

julia> cum_effects.std_errors  # Standard errors
40-element Vector{Float64}:
 1.6669189569635976
 1.5663756814986112
 
 1.728900903879408
 1.8318442896860898

Plotting

Simple Event Study Plot

using Makie, CairoMakie
m = fit_bjs_dynamic(df; y=:dep_var, id=:unit, t=:year, g=:g,cluster=:unit);
   fig = plot_event_study(m; title="BJS Event Study", color=:steelblue)

Event Study

Event Study with Multiple Estimators

result = plot_comparison(df; 
       y=:dep_var, id=:unit, t=:year, g=:g,
       models=[:bjs, :gardner, :sunab, :twfe],
       cluster=:unit).figure

Comparison

Common Parameters

All estimator functions accept:

  • df::DataFrame: Panel dataset
  • y::Symbol: Outcome variable name
  • id::Symbol: Unit identifier
  • t::Symbol: Time period variable
  • g::Symbol: Treatment timing variable
  • controls::Vector{Symbol}: Additional controls (default: Symbol[])
  • cluster::Symbol: Clustering variable (default: clusters by id)
  • weights::Union{Nothing,Symbol}: Observation weights (default: nothing)

R Package Equivalents

Julia R STATA
fit_bjs_imputation() - did_imputation
fit_did2s_static() did2s::did2s()
fit_sunab() fixest::feols(y ~ sunab(g, t) | id + t) -
fit_twfe_dynamic() fixest::feols(y ~ i(event_time) | id + t) -

References

  • Borusyak, K., Jaravel, X., & Spiess, J. (2023). Revisiting event study designs: Robust and efficient estimation.
  • Gardner, J. (2022). Two-stage differences in differences.
  • Sun, L., & Abraham, S. (2021). Estimating dynamic treatment effects in event studies with heterogeneous treatment effects. Journal of Econometrics, 225(2), 175-199.

About

Borusyak, Jaravel, Spiess (2023), Gardner (2021), Sun & Abraham (2021) staggered difference in differences estimators in Julia

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages