Treatment Effects with Multiple Periods and Groups
Overview
The standard Difference-in-Differences (DID) setup involves two periods and two groups -- a treated group and untreated group. Many applications of DID methods involve more than two periods and have individuals that are treated at different points in time. This package contains tools for computing average treatment effect parameters in Difference in Differences setups with more than two periods and with variation in treatment timing using the methods developed in Callaway and Sant'Anna (2021) doi:10.1016/j.jeconom.2020.12.001. The main parameters are group-time average treatment effects which are the average treatment effect for a particular group at a particular time. These can be aggregated into a fewer number of treatment effect parameters, and the package deals with the cases where there is selective treatment timing, dynamic treatment effects, calendar time effects, or combinations of these. There are also functions for testing the Difference in Differences assumption, and plotting group-time average treatment effects.
- Bug fix (
att_gt()): withcontrol_group = "notyettreated"and no never-treated group, the presence of already-treated units (treated in or before the first period, possibly viaanticipation) no longer affects theATT(g,t)of the other groups. The last-treated cohort, which serves as the not-yet-treated comparison group in this design, was being deleted from the data along with the always-treated units — biasing the remaining estimates or turning them intoNA— and is now retained.control_group = "nevertreated"was unaffected. - Bug fix (
fix_weights = "varying"standard errors): on a *balanced* panel,fix_weights = "varying"reported standard errors (analytic and bootstrap, and allaggte()aggregations) that were exactly **2× too large**. Point estimates were correct. The repeated-cross-section influence function is normalized over the2·n_unitsstacked observations; folding the pre- and post-period halves to the unit level was missing the corresponding1/2. Fixed in both code paths; verified against a Monte Carlo (the corrected SE now matches the empirical sampling standard deviation, and equals the panel-estimator SE when weights are time-invariant). Repeated cross sections and unbalanced panels were unaffected. aggte()now fails gracefully instead of with cryptic errors when an aggregation has an empty or all-NAselection:type = "calendar"withna.rm = TRUEdrops calendar periods whose post-treatment cells are allNA(analogous to the existingtype = "group"guard) rather than erroring; andtype = "simple"/"dynamic"with amin_e/max_ewindow that excludes every post-treatment period now return a clear message instead of an internal"report this as a bug"/"non-numeric argument"error.att_gt()now rejects a negativegnameup front with a clear message in bothfaster_mode = TRUEandFALSE. Previously negative cohort codes (out of spec —gnamemust be0for never-treated or a positive treatment time) were silently accepted on the fast path but errored on the slow path.- The parallel multiplier bootstrap (
bstrap = TRUE, pl = TRUE, cores > 1, when the influence function has more than 2500 rows — i.e. more than 2500 units, or more than 2500 clusters when clustered standard errors are used) is now reproducible under a fixedset.seed(). It previously used the default Mersenne-Twister RNG insideparallel::mclapply(), whose forked workers re-seed non-deterministically, so bootstrap standard errors and uniform-band critical values drifted between identical-seed runs. It now uses L'Ecuyer-CMRG parallel RNG streams (and restores the caller's RNG kind on exit). Point estimates were always unaffected. - Fixed a crash in the parallel bootstrap when
biters < cores(withpl = TRUE,cores > 1, and more than 2500 influence-function rows — units, or clusters under clustered inference): the per-core work split could produce a negative chunk size. The split is now always non-negative. aggte(type = "calendar")now warns whenmin_e,max_e, orbalance_eis supplied, since these event-study options do not apply to calendar-time aggregation (the unrestricted, correct calendar effects are returned, as before).
From NEWS.md in the release
Install
Health
- OK13 OK2026-08-05
- NOTE12 OK, 1 NOTE2026-08-01
- OK13 OK2026-06-09
- ERROR12 OK, 1 ERROR2026-06-08
- OK13 OK2026-05-02
Show 2 earlier changesHide 2 earlier changes
- ERROR11 OK, 1 ERROR2026-04-25
- OK14 OK2026-03-10
Documentation
- Help pages
- 44 (12 internal)includes a package overview page
- Examples that run
- 33%1 run in a plain check · 2 never run
- Exported functions with examples
- 13%
- Documented parameters
- 91%
- Return-value docs
- 83%
- Help pages citing references
- 5%
Downloads
Repository
- PRs merged (all time)
- 74%
- Median days to close, 50 most recently updated closed issues
- 757
- Median days to close, 50 most recently updated closed PRs
- 0
Stars over time
Forks over time
Releases over time
Issues over time
PRs over time
Commits over time
10 development-tooling and community-health practices detected across 6 families in the upstream repository
Checks run against github.com/bcallaway11/did on 2026-10-18.
The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel
GitHub Pages site last deployed 2026-08-28
pkgdown site last built 2026-07-30
Show all practicesHide 2 practices
This repository shows signs of AI coding tools.
- Claude Codefirst seen 2025-11-08Named in .Rbuildignore: .claude, CLAUDE.mdNamed in .gitignore: .claude, CLAUDE.mdPull request it wrote: opened by a project memberCommits: at least 16 crediting it in the message
- GitHub Copilotfirst seen 2026-03-01Pull request: opened by its own account
- Claude Sonnet 4.610 commits · Jun 2026
- Claude Opus 4.65 commits · Apr 2026
- Claude Sonnet 51 commit · Jul 2026
Dependencies
Installing did adds 45 packages (25 with compiled code, 59 MB of source tarballs). Heaviest: BH 14 MB, stringi 11 MB, ggplot2 6.0 MB.
Show all 14 packagesHide all 14 packages
Code & Tests
Datasets
People & History
Pick two releases to compare their code metrics.
- 2.5.1Latest
- 2.5.02026-06-13 · diff ↗
- RR 4.6.0 released · 2026-04-24
- 2.3.0
- RR 4.5.0 released · 2025-04-11
- RR 4.4.0 released · 2024-04-24
- RR 4.3.0 released · 2023-04-21
- unarchivedReturned to CRAN2022-07-20
- 2.1.22022-07-20 · diff ↗
- archivedRemoved from CRAN2022-07-09requires archived package 'BMisc'
- RR 4.2.0 released · 2022-04-22
- 2.1.12022-01-27 · diff ↗
- 2.1.02021-12-10 · diff ↗ ·
removed 2 exports
mp.spatt, mp.spatt.testadded 6 exports
build_sim_dataset, glance, reset.sim, sim, tidy, trimmer - RR 4.1.0 released · 2021-05-18
- 2.0.02020-12-11 · diff ↗ ·
removed 3 exports
compute.mp.spatt, expf, onefunadded 11 exports
AGGTEobj, DIDparams, aggte, att_gt, compute.att_gt, conditional_did_pretest, mboot, pre_process_did, process_attgt, splot, test.mboot - RR 4.0.0 released · 2020-04-24
Show 14 earlier eventsHide 14 earlier events
- unarchivedReturned to CRAN2020-02-18
- 1.2.32020-02-18 · diff ↗
- archivedRemoved from CRAN2020-02-16check problems were not corrected in time
- 1.2.22019-06-21 · diff ↗
- 1.2.12019-06-14 · diff ↗
- RR 3.6.0 released · 2019-04-26
- 1.2.02018-10-17 · diff ↗
- unarchivedReturned to CRAN2018-09-11
- 1.1.22018-09-11 · diff ↗
- archivedRemoved from CRAN2018-08-19check problems were not corrected despite reminders
- 1.1.02018-07-11 · diff ↗
- RR 3.5.0 released · 2018-04-23
- 1.0.02018-04-03
- RR 3.4.0 released · 2017-04-21
Package metadata
- First published
- 2018-04-03
- Total releases
- 14 / 8 yrs
- License
- GPL-3 OSI
- Minimum R
- ≥ 4.1.0
- Bundled data
- 28 KB / 1 file
- Download size
- 4.5 MB
Cite
Cite this package
Run in R for the authors' preferred citation:
citation("did")The package provides a citation file that builds its entry when R runs it. Run citation() to see it.
The repository also keeps a CITATION.cff.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-20, which the citation names so these numbers can be found later. More on citing and the projects behind them.