Regression Adjustment for Heterogeneous Difference-in-Differences in Stata: Comparing xthdidregress and lwdid

I am currently attending the Timberlake Econometrics Summer School at Churchill College, Cambridge, where I am following Professor Jeffrey Wooldridge’s class. This course provided an excellent opportunity to revisit my earlier blog post on heterogeneous difference-in-differences with Stata.

In this post, I compare two implementations of the regression-adjustment estimator for staggered difference-in-differences:

  • Stata’s official xthdidregress ra command;
  • the new community-contributed lwdid command developed by Soo Jeong Lee and Jeffrey Wooldridge.

The objective is deliberately narrow. I estimate the same regression-adjustment model with both commands. I do not compare regression adjustment with AIPW, IPWRA, or extended two-way fixed effects. Such comparisons would involve different estimators and would not generally produce identical estimates.

The main result is clear: once the sample, covariates, control group, reference period, clustering level, and aggregation weights are aligned, the two commands produce numerically identical point estimates. Their standard errors and confidence bands, however, differ because the commands implement different inference procedures.

The minimum-wage application

I use the same minwage dataset as in my original blog. It contains a balanced panel of 2,284 counties observed annually between 2001 and 2007:

2,284×7=15,988 observations.2,284 \times 7 = 15,988 \text{ observations}.

The outcome variable, lemp, is the logarithm of county employment. Treatment occurs at the state level, with treatment cohorts beginning in 2004, 2006, and 2007. Counties in states that are never treated provide the comparison group.

The covariate specification is unchanged:

global covars i.region pop medinc white hs pov c.pop#c.pop ///
    c.medinc#c.medinc

It includes region indicators, population, median income, demographic and educational variables, poverty, and quadratic terms for population and median income.

The county is the panel unit, but treatment is assigned at the state level. Accordingly, the estimation uses countyreal as the panel identifier and clusters inference at the state level. There are 29 state clusters.

The regression-adjustment estimator

For each treatment cohort gg and calendar year tt, define the change relative to the last pretreatment year:

ΔgYit=YitYi,g1.\Delta_g Y_{it}=Y_{it}-Y_{i,g-1}.

Regression adjustment uses the never-treated observations to estimate the expected untreated change conditional on the covariates:

mg,t(Xi)=E(ΔgYitXi,Gi=0).m_{g,t}(X_i) = E\left(\Delta_gY_{it}\mid X_i,G_i=0\right).

The cohort-time treatment effect is obtained by averaging the difference between the observed change and the estimated counterfactual change among the units belonging to cohort gg:

ATT(g,t)=E[ΔgYitmg,t(Xi)Gi=g].ATT(g,t) = E\left[ \Delta_gY_{it}-m_{g,t}(X_i) \mid G_i=g \right].

Regression adjustment is not doubly robust. Its validity depends on the usual difference-in-differences assumptions—including no anticipation and conditional parallel trends—as well as an appropriately specified outcome regression.

Estimation with xthdidregress

The first estimator is:

local reps 999
local seed 271828

xthdidregress ra (lemp $covars) (treat), ///
    group(state) controlgroup(never) basetime(common)

Two options deserve particular attention.

First, controlgroup(never) makes the never-treated comparison group explicit. This is already the default for xthdidregress, but stating it explicitly helps align the two commands.

Second, basetime(common) uses g1g-1, the final pretreatment period, as the reference year for every pretreatment and post-treatment estimate.

By default, xthdidregress uses an adaptive reference period before treatment: a pretreatment effect for year tt compares tt with t1t-1. Post-treatment effects always use g1g-1. The common-base option therefore changes the presentation of the pretreatment coefficients but leaves all post-treatment estimates unchanged. This distinction is explained in the xthdidregress documentation.

I save the estimation sample so that lwdid uses exactly the same observations:

tempvar sample_ra
generate byte `sample_ra' = e(sample)

The overall and event-time effects are obtained as follows:

estat aggregation, overall weights(timecohort)

estat aggregation, dynamic weights(timecohort) ///
    sci(reps(`reps') rseed(`seed')) ///
    graph(name(d1, replace))

graph export "figures\event.png", as(png) ///
    name("d1") replace

The weights(timecohort) option weights the contributing cohort-time effects by the number of treated observations in each cell. The sci() option requests simultaneous rather than pointwise confidence intervals.

The equivalent specification with lwdid

The lwdid command implements the transformation-based rolling difference-in-differences estimators developed by Lee and Wooldridge. It can be installed from SSC:

ssc install lwdid, replace

Before estimation, I use fvrevar to expand the factor-variable and quadratic terms used in the original model:

fvrevar $covars
local covars_lwdid "`r(varlist)'"

This does not change the model. It simply converts expressions such as i.region, c.pop#c.pop, and c.medinc#c.medinc into the corresponding numeric variables required by lwdid.

The aligned regression-adjustment specification is:

lwdid lemp `covars_lwdid' if `sample_ra', ///
    ivar(countyreal) tvar(year) gvar(_did_cohort) ///
    rolling(demean) pre(1) method(ra) never ///
    cluster(state) attgt graph level(95) ///
    reps(`reps') seed(`seed') ///
    gopts(name(lwdid_event, replace))

graph export "figures\lwdid_event.png", as(png) ///
    name("lwdid_event") replace

The correspondence between the options is important:

  • ivar(countyreal) identifies the county panel.
  • tvar(year) identifies calendar time.
  • gvar(_did_cohort) uses the cohort variable constructed by xthdidregress.
  • never restricts the comparison group to never-treated states.
  • cluster(state) clusters inference at the treatment-assignment level.
  • method(ra) selects regression adjustment.
  • rolling(demean) pre(1) subtracts the final pretreatment outcome.

With pre(1), the pretreatment mean contains only one observation. Therefore, demeaning is simply:

YitYi,g1.Y_{it}-Y_{i,g-1}.

This is precisely the transformation used by xthdidregress ra with basetime(common). More details about this transformation approach are available in Lee and Wooldridge and the lwdid documentation.

Graphical comparison

Figure 1. Event-time ATETs estimated with xthdidregress ra. The dashed red line reports the point estimates, while the grey envelope shows the 95% simultaneous confidence intervals. Exposure −1 is the common reference period and is omitted.

Figure 2. Event-time WATT(r) estimates obtained with lwdid, method(ra). Pretreatment estimates are shown in blue and post-treatment estimates in red. The vertical intervals are 95% simultaneous confidence bands. Exposure −1 is normalized to zero.

The estimated paths are visually very similar. Numerically, the point estimates are identical up to the displayed rounding precision.

The only graphical difference in the normalization is that xthdidregress omits exposure −1, whereas lwdid explicitly displays it as zero.

Comparison of the point estimates

The post-treatment event-time results are:

Exposure timexthdidregresslwdidExact employment effect
0−0.0245258−0.0245258−2.42%
1−0.0524273−0.0524273−5.11%
2−0.0751323−0.0751323−7.24%
3−0.0840835−0.0840835−8.06%

The exact percentage transformations are computed as:

100[exp(β^)1].100\left[\exp(\widehat{\beta})-1\right].

The largest difference between the reported coefficients from the two commands is less than 5×1085\times10^{-8}, which is entirely attributable to displayed rounding.

The underlying seven post-treatment ATT(g,t)ATT(g,t) estimates also coincide. The match is therefore not created by the event-time aggregation: both commands first produce the same cohort-time estimates and then aggregate them in the same way.

The weighted overall post-treatment effect is also identical:

ATT^overall=0.0385318.\widehat{ATT}_{overall}=-0.0385318.

Because employment is expressed in logarithms, this corresponds to an average employment effect of approximately:

100[exp(0.0385318)1]=3.78%.100\left[\exp(-0.0385318)-1\right] = -3.78\%.

This overall estimate is not the simple arithmetic mean of the four event-time coefficients. It is a treated-observation-weighted average of the seven available post-treatment ATT(g,t)ATT(g,t) cells.

The composition of the event-time estimates also changes with the horizon. At exposure zero, all three treatment cohorts contribute. At exposure one, only the 2004 and 2006 cohorts contribute. At exposures two and three, only the 2004 cohort remains observable. The increasingly negative dynamic path should therefore be interpreted with this changing cohort composition in mind.

Why are the confidence intervals different?

Identical point estimates do not imply identical inference.

For the overall effect, the commands report:

CommandEstimateStandard error95% pointwise interval
xthdidregress−0.03853180.0111631[−0.0604111, −0.0166525]
lwdid−0.03853180.0071951[−0.0526340, −0.0244296]

Stata’s sci() option constructs multiplier-bootstrap simultaneous intervals. The lwdid event graph uses its own clustered wild-bootstrap procedure. Consequently, using the same number of replications and the same random-number seed does not make the confidence bands identical.

The difference is particularly visible at exposure zero:

  • the xthdidregress simultaneous interval is [−0.05096, 0.00191];
  • the lwdid simultaneous band is [−0.04155, −0.00750].

The first includes zero, while the second does not. From exposure one to exposure three, both procedures produce simultaneous bands that exclude zero.

All the pretreatment simultaneous bands include zero under both procedures. Moreover, lwdid reports:

Pre_avg=0.0020,p=0.867.Pre\_avg=0.0020,\qquad p=0.867.

This is reassuring, but it should not be overinterpreted. Pre_avg is an average of pretreatment effects, not a joint test that every individual lead equals zero. More generally, a failure to reject pretreatment effects does not prove that parallel trends holds.

It is also important to distinguish the pointwise p-values displayed by lwdid from the simultaneous confidence bands shown in its event-study graph. A pointwise p-value may be below 5% even when the corresponding simultaneous band contains zero because the simultaneous band accounts for inference across the entire event-time path.

What does this exercise establish?

This exercise does not establish a general equivalence between the default implementations of xthdidregress and lwdid.

Their defaults differ in important ways. In particular:

  • xthdidregress uses an adaptive reference period for pretreatment effects by default;
  • lwdid, rolling(demean) uses all available pretreatment periods unless pre(1) is specified;
  • xthdidregress uses never-treated observations as its default control group;
  • lwdid must be given the never option to exclude not-yet-treated observations from the comparison group.

The appropriate conclusion is therefore more precise:

After aligning the estimation sample, covariates, treatment cohorts, never-treated comparison group, common g1g-1 reference period, clustering level, and time-cohort weights, xthdidregress ra and lwdid, method(ra) produce the same cohort-time, event-time, and overall point estimates in this minimum-wage application.

Their standard errors and confidence bands remain different because inference is implemented differently.

This example illustrates a broader econometric lesson: when comparing estimators across commands, matching the estimator’s name is not sufficient. We must align the entire estimand—the sample, controls, reference period, comparison group, weighting scheme, and aggregation rule.

References

Callaway, B., and P. H. C. Sant’Anna. 2021. “Difference-in-Differences with Multiple Time Periods.” Journal of Econometrics 225(2): 200–230.

Lee, S. J., and J. M. Wooldridge. “A Simple Transformation Approach to Difference-in-Differences Estimation for Panel Data.”

Lee, S. J., and J. M. Wooldridge. “LWDID: Rolling Difference-in-Differences Estimator for Small-N and Large-N Panel Data.” Statistical Software Components.

StataCorp. xthdidregress: Heterogeneous Difference-in-Differences for Panel Data.

Full code

// Clear the console and the data

cls
clear
graph drop _all

// Change the folder for the current directory

cd "C:\Users\jamel\Dropbox\stata\hdidweb"

// Open a log

capture log close
log using hdidweb_ra_lwdid.log, replace text

// Use the same data as in the blog

use minwage

describe
xtdescribe

sum
xtsum

capture mkdir "figures"

// Use the exact covariate specification from the blog

global covars i.region pop medinc white hs pov c.pop#c.pop  ///
    c.medinc#c.medinc

// Use the same number of replications and the same seed for both commands

local reps 999
local seed 271828

// -----------------------------------------------------------------------------
// 1. xthdidregress: regression adjustment
// -----------------------------------------------------------------------------

// basetime(common) uses g-1 for all pretreatment comparisons.
// This is the only change needed to align the full event-study path with
// lwdid, pre(1). It does not change the post-treatment estimates.

xthdidregress ra (lemp $covars) (treat),                  ///
    group(state) controlgroup(never) basetime(common)

// Keep exactly the same estimation sample for lwdid

tempvar sample_ra
generate byte `sample_ra' = e(sample)

// Plot the cohort-time ATETs with simultaneous 95% confidence bands

estat atetplot, sci(reps(`reps') rseed(`seed'))           ///
    name(atet, replace)
graph export "figures\atetplot.png", as(png)             ///
    name("atet") replace

// Overall post-treatment ATET
// This is directly comparable with Post_avg reported by lwdid.

estat aggregation, overall weights(timecohort)

// Event study with simultaneous 95% confidence bands

estat aggregation, dynamic weights(timecohort)            ///
    sci(reps(`reps') rseed(`seed'))                       ///
    graph(name(d1, replace))
graph export "figures\event.png", as(png)                ///
    name("d1") replace

// ATETs over cohort

estat aggregation, cohort graph(name(c1, replace))
graph export "figures\cohort.png", as(png)               ///
    name("c1") replace

// ATETs across calendar time

estat aggregation, time graph(name(t1, replace))
graph export "figures\time.png", as(png)                 ///
    name("t1") replace

// -----------------------------------------------------------------------------
// 2. lwdid: the equivalent regression-adjustment specification
// -----------------------------------------------------------------------------

// lwdid requires numeric covariates. fvrevar expands the factor-variable
// terms without changing the covariate specification.

fvrevar $covars
local covars_lwdid "`r(varlist)'"

// _did_cohort is created above by xthdidregress from treat and state.
// The two estimators therefore use the same sample, cohorts, controls,
// covariates, reference period, treatment level, and clustering level.

lwdid lemp `covars_lwdid' if `sample_ra',                 ///
    ivar(countyreal) tvar(year) gvar(_did_cohort)         ///
    rolling(demean) pre(1) method(ra) never               ///
    cluster(state) attgt graph level(95)                  ///
    reps(`reps') seed(`seed')                             ///
    gopts(name(lwdid_event, replace))

// The native lwdid event-study graph contains simultaneous 95% bands.

graph export "figures\lwdid_event.png", as(png)          ///
    name("lwdid_event") replace

log close _all

Full results

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
      name:  <unnamed>
       log:  C:\Users\jamel\Dropbox\stata\hdidweb\hdidweb_ra_lwdid.log
  log type:  text
 opened on:  21 Jul 2026, 20:07:26

. 
. // Use the same data as in the blog
. 
. use minwage
(Written by R.              )

. 
. describe

Contains data from minwage.dta
 Observations:        15,988                  Written by R.              
    Variables:            24                  3 May 2023 10:14
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Variable      Storage   Display    Value
    name         type    format    label      Variable label
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
state_name      str14   %14s                  state_name
county_name     str20   %20s                  county_name
emp0A01_BS      long    %9.0g                 emp0A01_BS
year            long    %9.0g                 year
quarter         double  %9.0g                 quarter
countyreal      double  %9.0g                 countyreal
censusdiv       long    %9.0g      censusdiv
                                              censusdiv
FIPS            double  %9.0g                 FIPS
msa             byte    %9.0g                 msa
pop             double  %9.0g                 pop
white           double  %9.0g                 white
black           double  %9.0g                 black
hs              double  %9.0g                 hs
col             double  %9.0g                 col
medinc          double  %9.0g                 medinc
pov             double  %9.0g                 pov
nssi            long    %9.0g                 nssi
first_treat     double  %9.0g                 first.treat
lemp            double  %9.0g                 lemp
lpop            double  %9.0g                 lpop
lmedinc         double  %9.0g                 lmedinc
region          long    %9.0g      region     region
treat           float   %9.0g                 
state           long    %14.0g     state      state_name
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sorted by: countyreal  year

. xtdescribe

countyreal:  8001, 8003, ..., 55141                          n =       2284
    year:  2001, 2002, ..., 2007                             T =          7
           Delta(year) = 1 unit
           Span(year)  = 7 periods
           (countyreal*year uniquely identifies each observation)

Distribution of T_i:   min      5%     25%       50%       75%     95%     max
                         7       7       7         7         7       7       7

     Freq.  Percent    Cum. |  Pattern
 ---------------------------+---------
     2284    100.00  100.00 |  1111111
 ---------------------------+---------
     2284    100.00         |  XXXXXXX

. 
. sum

    Variable |        Obs        Mean    Std. dev.       Min        Max
-------------+---------------------------------------------------------
  state_name |          0
 county_name |          0
  emp0A01_BS |     15,988    1086.871    3162.274          3      88246
        year |     15,988        2004    2.000063       2001       2007
     quarter |     15,988           1           0          1          1
-------------+---------------------------------------------------------
  countyreal |     15,988    32429.32    14042.17       8001      55141
   censusdiv |     15,988    5.047723    1.613506          3          8
        FIPS |     15,988    32429.32    14042.17       8001      55141
         msa |     15,988           1           0          1          1
         pop |     15,988    69.66555     200.788       .729   5376.741
-------------+---------------------------------------------------------
       white |     15,988    .8529558    .1511508       .045       .995
       black |     15,988    .0840902    .1358814          0        .79
          hs |     15,988    .5661664    .0732582       .249       .744
         col |     15,988    .1321392    .0634244       .037       .534
      medinc |     15,988     32.6927    7.732934     14.178     77.513
-------------+---------------------------------------------------------
         pov |     15,988    .1469785    .0612621       .019       .467
        nssi |     15,988    1396.727    4806.915          0     156340
 first_treat |     15,988    796.7715    981.7723          0       2007
        lemp |     15,988    5.714803    1.525451   1.098612   11.38788
        lpop |     15,988    3.224796    1.304159  -.3160815   8.589838
-------------+---------------------------------------------------------
     lmedinc |     15,988    3.461655    .2226008   2.651691   4.350446
      region |     15,988    2.660245    .6491307          2          4
       treat |     15,988    .0894421    .2853897          0          1
       state |     15,988    15.18389    8.737705          1         29

. xtsum

Variable         |      Mean   Std. dev.       Min        Max |    Observations
-----------------+--------------------------------------------+----------------
state_~e overall |         .          .          .          . |     N =       0
         between |                    .          .          . |     n =       0
         within  |                    .          .          . |     T =       .
                 |                                            |
county~e overall |         .          .          .          . |     N =       0
         between |                    .          .          . |     n =       0
         within  |                    .          .          . |     T =       .
                 |                                            |
emp0A0~S overall |  1086.871   3162.274          3      88246 |     N =   15988
         between |             3140.371   5.285714   70551.14 |     n =    2284
         within  |             376.4976  -5666.272   18781.73 |     T =       7
                 |                                            |
year     overall |      2004   2.000063       2001       2007 |     N =   15988
         between |                    0       2004       2004 |     n =    2284
         within  |             2.000063       2001       2007 |     T =       7
                 |                                            |
quarter  overall |         1          0          1          1 |     N =   15988
         between |                    0          1          1 |     n =    2284
         within  |                    0          1          1 |     T =       7
                 |                                            |
county~l overall |  32429.32   14042.17       8001      55141 |     N =   15988
         between |             14044.81       8001      55141 |     n =    2284
         within  |                    0   32429.32   32429.32 |     T =       7
                 |                                            |
census~v overall |  5.047723   1.613506          3          8 |     N =   15988
         between |             1.613809          3          8 |     n =    2284
         within  |                    0   5.047723   5.047723 |     T =       7
                 |                                            |
FIPS     overall |  32429.32   14042.17       8001      55141 |     N =   15988
         between |             14044.81       8001      55141 |     n =    2284
         within  |                    0   32429.32   32429.32 |     T =       7
                 |                                            |
msa      overall |         1          0          1          1 |     N =   15988
         between |                    0          1          1 |     n =    2284
         within  |                    0          1          1 |     T =       7
                 |                                            |
pop      overall |  69.66555    200.788       .729   5376.741 |     N =   15988
         between |             200.8257       .729   5376.741 |     n =    2284
         within  |             2.81e-14   69.66555   69.66555 |     T =       7
                 |                                            |
white    overall |  .8529558   .1511508       .045       .995 |     N =   15988
         between |             .1511791       .045       .995 |     n =    2284
         within  |             1.06e-16   .8529558   .8529558 |     T =       7
                 |                                            |
black    overall |  .0840902   .1358814          0        .79 |     N =   15988
         between |             .1359069          0        .79 |     n =    2284
         within  |             1.95e-17   .0840902   .0840902 |     T =       7
                 |                                            |
hs       overall |  .5661664   .0732582       .249       .744 |     N =   15988
         between |              .073272       .249       .744 |     n =    2284
         within  |             6.50e-17   .5661664   .5661664 |     T =       7
                 |                                            |
col      overall |  .1321392   .0634244       .037       .534 |     N =   15988
         between |             .0634363       .037       .534 |     n =    2284
         within  |             1.74e-17   .1321392   .1321392 |     T =       7
                 |                                            |
medinc   overall |   32.6927   7.732934     14.178     77.513 |     N =   15988
         between |             7.734386     14.178     77.513 |     n =    2284
         within  |             3.84e-15    32.6927    32.6927 |     T =       7
                 |                                            |
pov      overall |  .1469785   .0612621       .019       .467 |     N =   15988
         between |             .0612736       .019       .467 |     n =    2284
         within  |             1.93e-17   .1469785   .1469785 |     T =       7
                 |                                            |
nssi     overall |  1396.727   4806.915          0     156340 |     N =   15988
         between |             4807.817          0     156340 |     n =    2284
         within  |                    0   1396.727   1396.727 |     T =       7
                 |                                            |
first_~t overall |  796.7715   981.7723          0       2007 |     N =   15988
         between |             981.9565          0       2007 |     n =    2284
         within  |                    0   796.7715   796.7715 |     T =       7
                 |                                            |
lemp     overall |  5.714803   1.525451   1.098612   11.38788 |     N =   15988
         between |              1.51902   1.594888   11.15736 |     n =    2284
         within  |             .1429878   4.033124    7.03562 |     T =       7
                 |                                            |
lpop     overall |  3.224796   1.304159  -.3160815   8.589838 |     N =   15988
         between |             1.304404  -.3160815   8.589838 |     n =    2284
         within  |             4.02e-16   3.224796   3.224796 |     T =       7
                 |                                            |
lmedinc  overall |  3.461655   .2226008   2.651691   4.350446 |     N =   15988
         between |             .2226426   2.651691   4.350446 |     n =    2284
         within  |             4.34e-16   3.461655   3.461655 |     T =       7
                 |                                            |
region   overall |  2.660245   .6491307          2          4 |     N =   15988
         between |             .6492525          2          4 |     n =    2284
         within  |                    0   2.660245   2.660245 |     T =       7
                 |                                            |
treat    overall |  .0894421   .2853897          0          1 |     N =   15988
         between |             .1396193          0   .5714286 |     n =    2284
         within  |             .2489198  -.4819865   .9465849 |     T =       7
                 |                                            |
state    overall |  15.18389   8.737705          1         29 |     N =   15988
         between |             8.739345          1         29 |     n =    2284
         within  |                    0   15.18389   15.18389 |     T =       7

. 
. capture mkdir "figures"

. 
. // Use the exact covariate specification from the blog
. 
. global covars i.region pop medinc white hs pov c.pop#c.pop  ///
>     c.medinc#c.medinc

. 
. // Use the same number of replications and the same seed for both commands
. 
. local reps 999

. local seed 271828

. 
. // -----------------------------------------------------------------------------
. // 1. xthdidregress: regression adjustment
. // -----------------------------------------------------------------------------
. 
. // basetime(common) uses g-1 for all pretreatment comparisons.
. // This is the only change needed to align the full event-study path with
. // lwdid, pre(1). It does not change the post-treatment estimates.
. 
. xthdidregress ra (lemp $covars) (treat),                  ///
>     group(state) controlgroup(never) basetime(common)
note: variable _did_cohort, containing cohort indicators formed by treatment variable treat and group variable state, was added to the dataset using the estimation sample.

Computing ATET for each cohort and time:
Cohort 2004 (6): ...... done
Cohort 2006 (6): ...... done
Cohort 2007 (6): ...... done

Treatment and time information

Time variable: year
Time interval: 2001 to 2007
Control:       _did_cohort = 0
Treatment:     _did_cohort > 0
-------------------------------
                  | _did_cohort
------------------+------------
Number of cohorts |           4
------------------+------------
Number of obs     |
    Never treated |        9639
             2004 |         700
             2006 |        1561
             2007 |        4088
-------------------------------

Heterogeneous-treatment-effects regression           Number of obs    = 15,988
                                                     Number of panels =     29
Estimator:       Regression adjustment
Panel variable:  countyreal
Treatment level: state
Control group:   Never treated

                                 (Std. err. adjusted for 29 clusters in state)
------------------------------------------------------------------------------
             |               Robust
Cohort       |       ATET   std. err.      z    P>|z|     [95% conf. interval]
-------------+----------------------------------------------------------------
2004         |
        year |
       2001  |  -.0429959   .0118033    -3.64   0.000      -.06613   -.0198618
       2002  |  -.0149191   .0131769    -1.13   0.258    -.0407454    .0109072
       2004  |  -.0415691   .0119292    -3.48   0.000      -.06495   -.0181882
       2005  |   -.054816   .0084848    -6.46   0.000    -.0714459    -.038186
       2006  |  -.0751323   .0105228    -7.14   0.000    -.0957565   -.0545081
       2007  |  -.0840835   .0188487    -4.46   0.000    -.1210263   -.0471407
-------------+----------------------------------------------------------------
2006         |
        year |
       2001  |  -.0843448   .0515156    -1.64   0.102    -.1853134    .0166238
       2002  |  -.1013101   .0563677    -1.80   0.072    -.2117887    .0091686
       2003  |  -.0486257   .0451636    -1.08   0.282    -.1371446    .0398933
       2004  |  -.0312692   .0149548    -2.09   0.037    -.0605801   -.0019583
       2006  |  -.0063152   .0112098    -0.56   0.573     -.028286    .0156557
       2007  |  -.0513561   .0096761    -5.31   0.000     -.070321   -.0323912
-------------+----------------------------------------------------------------
2007         |
        year |
       2001  |   .0263036   .0312059     0.84   0.399     -.034859    .0874661
       2002  |   .0039442   .0278569     0.14   0.887    -.0506544    .0585427
       2003  |    .020518   .0228685     0.90   0.370    -.0243036    .0653395
       2004  |   .0351406   .0184571     1.90   0.057    -.0010348    .0713159
       2005  |    .039331   .0124343     3.16   0.002     .0149602    .0637018
       2007  |  -.0285611   .0139574    -2.05   0.041    -.0559172   -.0012051
------------------------------------------------------------------------------
Note: ATET computed using covariates.
Note: Base time for pretreatment ATETs is the last pretreatment period.

. 
. // Keep exactly the same estimation sample for lwdid
. 
. tempvar sample_ra

. generate byte `sample_ra' = e(sample)

. 
. // Plot the cohort-time ATETs with simultaneous 95% confidence bands
. 
. estat atetplot, sci(reps(`reps') rseed(`seed'))           ///
>     name(atet, replace)

. graph export "figures\atetplot.png", as(png)             ///
>     name("atet") replace
file figures\atetplot.png saved as PNG format

. 
. // Overall post-treatment ATET
. // This is directly comparable with Post_avg reported by lwdid.
. 
. estat aggregation, overall weights(timecohort)

Overall ATET                                            Number of obs = 15,988

                                 (Std. err. adjusted for 29 clusters in state)
------------------------------------------------------------------------------
             |               Robust
        lemp |       ATET   std. err.      z    P>|z|     [95% conf. interval]
-------------+----------------------------------------------------------------
       treat |
   (1 vs 0)  |  -.0385318   .0111631    -3.45   0.001    -.0604111   -.0166525
------------------------------------------------------------------------------
Note: Aggregation weights vary across times and cohorts.

. 
. // Event study with simultaneous 95% confidence bands
. 
. estat aggregation, dynamic weights(timecohort)            ///
>     sci(reps(`reps') rseed(`seed'))                       ///
>     graph(name(d1, replace))

Duration of exposure ATET               Number of obs = 15,988
                                        Replications  =    999

                 (Std. err. adjusted for 29 clusters in state)
--------------------------------------------------------------
             |   Observed   Bootstrap         Simultaneous
    Exposure |       ATET   std. err.     [95% conf. interval]
-------------+------------------------------------------------
          -6 |   .0263036    .033451     -.0622865    .1148936
          -5 |  -.0204529   .0268185     -.0914777    .0505719
          -4 |   -.013147    .028618     -.0889376    .0626435
          -3 |   .0059305   .0193205     -.0452369     .057098
          -2 |   .0159916   .0127214     -.0176992    .0496824
           0 |  -.0245258   .0099816     -.0509605    .0019089
           1 |  -.0524273   .0073847     -.0719845     -.03287
           2 |  -.0751323   .0097534     -.1009628   -.0493019
           3 |  -.0840835   .0156018     -.1254027   -.0427643
--------------------------------------------------------------
Note: Base time for pretreatment ATETs is the last
      pretreatment period.
Note: Exposure is the number of periods since the first
      treatment time.
Note: Aggregation weights vary across times and cohorts.
Note: Simultaneous confidence intervals provide inference
      across all aggregations simultaneously.

. graph export "figures\event.png", as(png)                ///
>     name("d1") replace
file figures\event.png saved as PNG format

. 
. // ATETs over cohort
. 
. estat aggregation, cohort graph(name(c1, replace))

ATET over cohort                                        Number of obs = 15,988

                                 (Std. err. adjusted for 29 clusters in state)
------------------------------------------------------------------------------
             |               Robust
      Cohort |       ATET   std. err.      z    P>|z|     [95% conf. interval]
-------------+----------------------------------------------------------------
        2004 |  -.0639002   .0115714    -5.52   0.000    -.0865798   -.0412207
        2006 |  -.0288356   .0076181    -3.79   0.000    -.0437669   -.0139044
        2007 |  -.0285611   .0139574    -2.05   0.041    -.0559172   -.0012051
------------------------------------------------------------------------------
Note: Aggregation weights vary across times and cohorts.

. graph export "figures\cohort.png", as(png)               ///
>     name("c1") replace
file figures\cohort.png saved as PNG format

. 
. // ATETs across calendar time
. 
. estat aggregation, time graph(name(t1, replace))

ATET over time                                          Number of obs = 15,988

                                 (Std. err. adjusted for 29 clusters in state)
------------------------------------------------------------------------------
             |               Robust
        Time |       ATET   std. err.      z    P>|z|     [95% conf. interval]
-------------+----------------------------------------------------------------
        2004 |  -.0415691   .0119292    -3.48   0.000      -.06495   -.0181882
        2005 |   -.054816   .0084848    -6.46   0.000    -.0714459    -.038186
        2006 |  -.0276208    .019351    -1.43   0.153    -.0655481    .0103066
        2007 |  -.0402872   .0124356    -3.24   0.001    -.0646605   -.0159138
------------------------------------------------------------------------------
Note: Aggregation weights vary across times and cohorts.

. graph export "figures\time.png", as(png)                 ///
>     name("t1") replace
file figures\time.png saved as PNG format

. 
. // -----------------------------------------------------------------------------
. // 2. lwdid: the equivalent regression-adjustment specification
. // -----------------------------------------------------------------------------
. 
. // lwdid requires numeric covariates. fvrevar expands the factor-variable
. // terms without changing the covariate specification.
. 
. fvrevar $covars

. local covars_lwdid "`r(varlist)'"

. 
. // _did_cohort is created above by xthdidregress from treat and state.
. // The two estimators therefore use the same sample, cohorts, controls,
. // covariates, reference period, treatment level, and clustering level.
. 
. lwdid lemp `covars_lwdid' if `sample_ra',                 ///
>     ivar(countyreal) tvar(year) gvar(_did_cohort)         ///
>     rolling(demean) pre(1) method(ra) never               ///
>     cluster(state) attgt graph level(95)                  ///
>     reps(`reps') seed(`seed')                             ///
>     gopts(name(lwdid_event, replace))
------------------------------------------------------------
 lwdid [large-N mode]  rolling=demean  method=ra
 pre(1): using last 1 pre-treatment period(s) for outcome transformation
 never: comparing each cohort g to never-treated only
------------------------------------------------------------

 Group-time ATT(g,t) estimates (post-period only)
--------------------------------------------------------------------------------------
g=2004
       year      ATT         Std. err.    t       P>|t|    [95% conf. interval]
--------------------------------------------------------------------------------------
         2004   -.04156913   .01766019    -2.35    0.019   -.07621121  -.00692705
         2005   -.05481597   .01982196    -2.77    0.006   -.09369855   -.0159334
         2006   -.07513232    .0196116    -3.83    0.000   -.11360227  -.03666237
         2007   -.08408352   .02132017    -3.94    0.000   -.12590498  -.04226205
--------------------------------------------------------------------------------------
g=2006
       year      ATT         Std. err.    t       P>|t|    [95% conf. interval]
--------------------------------------------------------------------------------------
         2006   -.00631516   .00891074    -0.71    0.479   -.02379326   .01116294
         2007   -.05135612   .00898016    -5.72    0.000   -.06897039  -.03374185
--------------------------------------------------------------------------------------
g=2007
       year      ATT         Std. err.    t       P>|t|    [95% conf. interval]
--------------------------------------------------------------------------------------
         2007   -.02856111   .00802487    -3.56    0.000   -.04429938  -.01282283
--------------------------------------------------------------------------------------


 Aggregated WATT(r) estimates
--------------------------------------------------------------------------------------------
  effect      WATT        Std. err.    t       P>|t|    [95% CI/band]            N cells
--------------------------------------------------------------------------------------------
    Pre_avg   .00202628   .01212299     0.17    0.867   -.02173435   .02578691           -
   Post_avg   -.0385318   .00719513    -5.36    0.000     -.052634  -.02442959           -
         -6   .02630355   .02458598     1.07    0.285   -.03127238   .08387949           1
         -5  -.02045292   .01653625    -1.24    0.216   -.05917784     .018272           2
         -4  -.01314704    .0147397    -0.89    0.372   -.04766475   .02137068           2
         -3   .00593051   .00804622     0.74    0.461   -.01291229   .02477331           3
         -2   .01599157   .00715227     2.24    0.025   -.00075775   .03274089           3
         -1           0           0        .        .            0           0           3
          0  -.02452578   .00727066    -3.37    0.001   -.04155235   -.0074992           3
          1  -.05242728   .00798902    -6.56    0.000   -.07113612  -.03371844           2
          2  -.07513232   .01073148    -7.00    0.000    -.1002635  -.05000114           1
          3  -.08408352   .01911183    -4.40    0.000   -.12883999  -.03932704           1
--------------------------------------------------------------------------------------------
Note: Pre_avg/Post_avg are weighted averages of the contributing ATT(g,t) cells;
      their confidence intervals are pointwise normal.
Note: For WATT(r) rows, [95% CI/band] reports simultaneous confidence bands
      (reps = 999).
Note: t statistics and p-values are pointwise normal.

. 
. // The native lwdid event-study graph contains simultaneous 95% bands.
. 
. graph export "figures\lwdid_event.png", as(png)          ///
>     name("lwdid_event") replace
file figures\lwdid_event.png saved as PNG format

. 
. log close _all
      name:  <unnamed>
       log:  C:\Users\jamel\Dropbox\stata\hdidweb\hdidweb_ra_lwdid.log
  log type:  text
 closed on:  21 Jul 2026, 20:07:34
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.