*! version 1.5 18oct2025

*! version 1.0 10sep2025

flexdid postestimation -- Postestimation tools for flexdid

Postestimation commands

The following postestimation command is of special interest after
flexdid:

Command Description

estat atet estimates ATETs
to characterize the heterogenity of treatment effects

Syntax of estat atet

estat atet, options

options

* overall[(overall_list)]
estimates overall ATET over all exposure times in overall_list; implies nograph

* byget[(exposure_list)]
estimates group X exposure time ATETs by each time period in exposure_list;
implies nograph

* byexposure[(exposure_list)]
estimates ATETs by each exposure time in exposure_list

* bycalendar[(calendar_list)]
estimates ATETs by each calendar time in calendar_list

* bycohort[(cohort_list)]
estimates ATETs by each treated cohort in cohort_list

* bygroup[(group_list)]
estimates ATETs by each treated group in group_list

for(if exp) estimates ATETs for the subpopulation
identified by the if exp expression

test(nulltype)
estimates an F test of a hypothesis of the ATETs specified by nulltype; nulltype must
be specified

nograph supresses the ATET plot

+ graph(marginsplot:graph_opts) affects rendition of the ATET plot

dydx estimates ATETs using the dydx option in margins;
useful when the default procedure fails to produce standard errors of the ATETs

nulltype

zero specifies the null hypothesis that all the ATETs are equal to zero

equal specifies the null hypothesis that all the ATETs are equal to each other

* One of these options is required.

+ graph_opts are most options included in marginsplot.

Description of estat atet

estat atet estimates ATETs to characterize the heterogenity of treatment
effects. In addition to tabular presentation of results, estat atet produces
plots of the effects in most cases. In addition, two important hypotheses, that
the ATETs are all equal to zero, or that the ATETs are equal to each other, can be tested.

Options for estat atet

overall[(numlist:overall_list)] estimates the overall ATET over all exposure time periods in overall_list.
The list can contain negative integers, which indicate leads or pre-treatment exposure time periods.
Specifying overall without arguments estimates the overall ATET over all treated exposure time periods,
i.e., from 0 to the last exposure time period observed in the data. This option does not produce a graph, i.e., it implies nograph.

byget[(numlist:exposure_list)] estimates ATETs for each group X exposure time period in exposure_list.
The list can contain negative integers, which indicate leads or pre-treatment periods.
Specifying byget without arguments estimates the ATETs for all group X exposure time periods, from the
earliest pre-treatment exposure time period to the last exposure time period observed in the data. This option does not produce a graph, i.e., it implies nograph.

byexposure[(numlist:exposure_list)] estimates ATETs for each exposure time period
in exposure_list. The list can contain negative integers, which indicate leads or pre-treatment periods
appropriate for use in the lags and leads specification.
Specifying byexposure without arguments estimates ATETs for all exposure time periods,
i.e., from 0 or the earliest pre-treatment exposure period in the lags only and the lags and leads
specifications respectively to the latest exposure time observed in the data.

bycalendar[(numlist:calendar_list)] estimates ATETs for each calendar time period in calendar_list.
Specifying bycalendar without arguments estimates ATETs for all calendar time periods
observed in the data.

bycohort[(numlist:cohort_list)] estimates ATETs for each treatment cohort in cohort_list.
Specifying bycohort without arguments estimates ATETs for each treated cohort in the data.

bygroup[(numlist:group_list)] estimates ATETs for each treated group in group_list.
Specifying bygroup without arguments estimates ATETs for each treated group in the data.

for(if exp) estimates ATETs for the subpopulation identified by the if exp expression.
if exp is a proper expression such as age<65 or age<65 & sex==1.

test(ttype) estimates an F test of a hypothesis of the ATETs specified by nulltype which
is either zero or equal.

zero specifies the null hypothesis that all the ATETs are equal to zero.

equal specifies the null hypothesis that all the ATETs are equal to each other.

nograph suppresses the ATET plot.

graph(graph_opts) affects the rendition of the ATET plot. graph_opts include most options
found in marginsplot.

dydx estimates ATETs using the dydx option in margins. The default
procedure is to use margins_contrast. Although margins_contrast is
substantially faster, on occasion it fails to produce standard errors of the estimates.
dydx is useful in those cases.

Remarks

estat atet, options, by default, uses
margins_contrast to aggregate regression estimates to ATETs and to compute their
standard errors. Although margins_contrast is fast and reliable, it can fail to
produce standard errors in some instances when the covariate matrix is not of full rank. Such
situations typically arise when ATETs at the group X exposure time level are required and when the
cluster-robust variance estimator is used along with cluster-units identical to the units
of group fixed effects and units at which treatment occurs. In such situations, margins
with the dydx option can handle rank and stability issues better, at the cost of
substantially greater computation time.

Examples of estat atet

Setup

. webuse hhabits

. egen chrt = min(year/hhabit), by(schools)

. replace chrt = 0 if chrt==.

Estimate the FLEX regression of the treatment, hhabit, on the outcome body mass index, bmi,
for cohorts of school districts by year, chrt, using the lagsandleads specification.

. flexdid bmi, tx(hhabit) group(chrt) time(year) specification(lagsandleads)

Estimate overall ATET of treatment over exposure time periods 0 to 3.

. estat atet, overall(0/3)

Estimate ATET of treatment for each exposure time period (the event study plot).

. estat atet, byexposure

Estimate the ATET for each exposure time period from 0 to 3.

. estat atet, byexposure(0/3)

Estimate the ATET for pre-treatment exposure time periods from -6 to -2, suppressing the ATET graph
and testing the null hypothesis that all pre-treatment exposure time effects are equal to zero.

. estat atet, byexposure(-6/-2) test(zero) nograph

Estimate the ATET for treatment exposure time periods from 0 to 6, suppressing the ATET graph
and testing the null hypothesis that all treatment exposure time effects are equal to each other.

. estat atet, byexposure(0/6) test(equal) nograph

Estimate the ATET for calendar years 2035 and 2038, supressing the ATET graph.

. estat atet, bycalendar(2035 2038) nograph

Estimate the FLEX regression of treatment on outcome body mass index, controlling for covariates,
for cohorts of school districts by year ; using the lagsandleads only specification.

. flexdid bmi i.girl medu, tx(hhabit) group(chrt) time(year)
specification(lagsandleads) vce(cluster schools)

Estimate the ATET for each group X exposure time period for the pre-treatment time periods, from
-6 to -2, and test whether the group X exposure time effects are equal to zero.

. estat atet, byget(-6/-2) test(zero)

Estimate the ATET for exposure periods from 0 to 6 for girl==1, supressing the ATET graph.

. estat atet, byexposure(0/6) for(girl==1) nograph

Stored results after estat atet

estat atet stores the following in r()

Macros

r(atettype) ATET "by" option specified

* r(test) test null hypothesis option specified

Scalars

* r(p) two-sided p-value

* r(F) F statistic

* r(df) test constraints degrees of freedom

* r(df_r) residual degrees of freedom

* r(drop) 1 if constraints were dropped, 0 otherwise

Matrices

r(table) matrix containing the ATETs with their standard errors,
test statistics, p-values, and confidence interval

r(b) ATET vector

r(V) variance-covariance matrix of the ATETs

* Only stored when test() is specified.