*! version 1.0.0 16apr2026 GuanpengYan

Title

didparallel -- testing parallel trends assumption (PTA) for difference-in-differences (DID) models

Syntax

didparallel
estimatename
,
treatvar(varname)
[options]

Required
treatvar(varname) name of treatment variable

Optional
baseperiod(#) base (omitted/reference) period; default is -1

range(# #) range of lags and leads to consider in event study

frame(framename) name of the Stata frame to store results

noomit include omitted (base period) coefficients in the graph

nofigure do not display figures

savegraph(prefix, [asis replace]) save all produced graphs to the current path.

xtset panelvar timevar must be used to declare a panel dataset; see [XT] xtset.

estimatename should be an estimation saved by estimates store; see [R] estimates store.

Description

didparallel provides an easy implementation of event study for difference-in-differences (DID) models,
where policy adoption may be synchronized or staggered. It only takes three simple steps:
(1) estimate the DID model; (2) store the result;
and (3) run didparallel by specifying the stored result and the treatment variable.

Options

Required

treatvar(varname) specifies a dummy variable indicating whether a unit is treated in a particular period.
didparallel automatically converts the variable into an indicator equal to 1 only in the period when a unit first becomes treated,
and shifts the indicator backward and forward relative to each unit's own timing to construct the leads and lags used in the test.
For example, consider a panel of 5 units observed over 5 periods,
where units start treatment in different periods (x denotes a treated observation and o an untreated observation):

t=1 t=2 t=3 t=4 t=5
+
+
i=1 | o o o o o |
i=2 | o o o o o |
i=3 | o o o o o |
i=4 | o o o x x |
i=5 | o x x x x |
+
+
original treatment
|
v
t=1 t=2 t=3 t=4 t=5 t=1 t=2 t=3 t=4 t=5 t=1 t=2 t=3 t=4 t=5
+
+ +
+ +
+
i=1 | o o o o o | i=1 | o o o o o | i=1 | o o o o o |
i=2 | o o o o o | i=2 | o o o o o | i=2 | o o o o o |
i=3 | o o o o o |<---- i=3 | o o o o o | ----> i=3 | o o o o o |
i=4 | o o x o o | i=4 | o o o x o | i=4 | o o o o x |
i=5 | x o o o o | i=5 | o x o o o | i=5 | o o x o o |
+
+ +
+ +
+
1-period lag initial treatment period 1-period lead
: :
| |
v v
t=1 t=2 t=3 t=4 t=5 t=1 t=2 t=3 t=4 t=5
+
+ +
+
i=1 | o o o o o | i=1 | o o o o o |
i=2 | o o o o o | i=2 | o o o o o |
i=3 | o o o o o | i=3 | o o o o o |
i=4 | x o o o o | i=4 | o o o o o |
i=5 | o o o o o | i=5 | o o o o x |
+
+ +
+
3-period lag 3-period lead

Optional

baseperiod(#) specifies the reference period as a negative integer, which defaults to -1.
The reference period is dropped from the estimation to avoid perfect multicollinearity.

range(# #) sets the range of lags and leads to consider in the event study.
For example, the option range(-10 10) would report a single regression coefficient capturing 10 or more periods prior/post treatment.
A missing value "." is allowed to leave either the lower or upper bound unrestricted.
The default range is to include all
possible lags and leads.

frame(framename) creates a Stata frame storing the estimates generated by the parallel trends test.
The frame named framename is replaced if it already exists, and created if not.

noomit keeps coefficients that Stata drops due to perfect collinearity in the plot.
By default, these omitted coefficients are excluded from the graph.

nofigure do not display figures. The default is to display all figures from parallel trend test if available.

savegraph(prefix, [asis replace]) automatically and iteratively calls the graph save to save all produced graphs to the current path,
where prefix specifies the prefix added to _graphname to form a file name,
that is, the graph named graphname is stored as prefix_graphname.gph.
asis and replace are options passed to graph save;
for details, see [G-2] graph save.
Note that this option only applies when nofigure is not specified.

Example 1: the impact of the Grand Canal's abandonment on rebellions (Cao and Chen, 2022)

. use cao_chen.dta, clear

. xtset county year

* Construct the difference-in-differences estimation and store the result

. reghdfe rebel canal_post, absorb(i.county i.year) vce(cluster county)

. estimates store did_cao_chen

* Implement the parallel trends test over a window of 10 periods before and after treatment

. didparallel did_cao_chen, treatvar(canal_post) range(-10 10)

Example 2: the impact of minimum wage increases on county-level teen employment (Callaway and Sant'Anna, 2021)

. use mpdta, clear

. xtset countyreal year

* Generate the treatment indicator

. gen treat_post = (first_treat <= year) & (first_treat > 0)

* Construct the difference-in-differences estimation and store the result

. reghdfe lemp treat_post, absorb(i.countyreal i.year) vce(cluster countyreal)

. estimates store mpdta_example

* Implement the parallel trends test

. didparallel mpdta_example, treatvar(treat_post)

Example 3: the impact of no-fault divorce reforms on suicide mortality (Stevenson and Wolfers, 2006)

. use bacon_example.dta, clear

. xtset stfips year

* Construct the difference-in-differences estimation and store the result

. regress asmrs post pcinc asmrh cases i.stfips i.year, vce(cluster stfips)

. estimates store bacon_example

* Implement the parallel trends test over a window of 10 periods before and after treatment

. didparallel bacon_example, treatvar(post) range(-10 10)

Stored results

In addition to the estimation results carried over from the regression command, didparallel stores the following in e():

Macros

e(graph) names of all produced graphs

e(frame) name of Stata frame

Compatibility

didparallel is confirmed to be compatible with official commands regress,
xtreg and areg as well as the third-party command reghdfe.
Other commands, though not specifically tested, may also be compatible with didparallel.

Reference

Stevenson, B., and Wolfers, J. 2006. Bargaining in the shadow of the law: Divorce laws and family distress. Quarterly Journal of Economics 121(1): 267-288.

Goodman-Bacon, A. 2021. Difference-in-differences with variation in treatment timing. Journal of Econometrics 225(2): 254-277.

Callaway, B., and Sant'Anna, P. H. C. 2021. Difference-in-differences with multiple time periods. Journal of Econometrics 225(2): 200-230.

Cao, Y., and Chen, S. 2022. Rebel on the canal: Disrupted trade access and social conflict in China, 1650-1911. American Economic Review 112(5): 1555-1590.

Author

Guanpeng Yan, Shandong University of Finance and Economics, CN

guanpengyan@yeah.net

Qiang Chen (correponding author), Shandong University, CN

www.econometrics-stata.com

qiang2chen2@126.com