nonabsdid is an R package for visualizing and comparing
heterogeneity-robust staggered DID event-study estimates under
non-absorbing binary treatment. Its example
output plot is as follows.
It covers existing multiple estimators and runs analysis via their
own packages, then puts their output on the same time axis, the same
tidy schema, and the same ggplot2 panel so you can compare
them at a glance.
Supported estimators:
DIDmultiplegtDYN.PanelMatch.fect:
IFE (interactive fixed effects)FE (two-way fixed-effects imputation)MC (matrix completion)Note: The DCDH estimator depends on
DIDmultiplegtDYN, which in turn requirespolars.polarsis not on CRAN, so install it from R-multiverse:Sys.setenv(NOT_CRAN = "true") install.packages("polars", repos = c("https://community.r-multiverse.org", "https://cloud.r-project.org"))
Plus an optional naive TWFE reference series (via
fixest) drawn in a neutral color so you can see what the
heterogeneity-robust estimators are correcting against.
# Development version from GitHub:
# install.packages("pak")
pak::pak("takuma1102/nonabsdid")You can install this package through r-universe.
install.packages(
"nonabsdid",
repos = c("https://takuma1102.r-universe.dev", getOption("repos"))
)The estimator packages themselves (DIDmultiplegtDYN,
PanelMatch, fect, fixest) are
listed in Suggests, so install the ones you plan to
use.
At the early stage of an analysis, use
nabs_event_study_simple() to get an initial sense of how
the event-study estimates look across estimators. It runs the
heterogeneity-robust estimators with reasonable defaults, fits a naive
TWFE reference, and gives you a single overlay plot to inspect before
moving on to estimator-specific tuning and robustness checks.
library(nonabsdid)
res <- nabs_event_study_simple(
mydata,
outcome = "y",
treatment = "d",
unit = "id",
time = "t"
)
res$plot # the figure
res$tidy # combined tidy tibble across methods
res$per_method # per-method tidy tibbles
res$fits # the native estimator objects, for diagnosticsIf a particular estimator’s package is not installed, that estimator is skipped with a message, and the remaining methods still produce output.
For publication-ready work, switch to the full wrapper or to the underlying packages directly. The unified wrapper:
res_dcdh <- nabs_event_study(mydata,
outcome = "y", treatment = "d",
unit = "id", time = "t",
method = "DCDH",
lags = 6, leads = 8,
controls = c("x1", "x2"))
res_pm <- nabs_event_study(mydata, ..., method = "PanelMatch")
res_ife <- nabs_event_study(mydata, ..., method = "IFE")
res_fe <- nabs_event_study(mydata, ..., method = "FE")
res_mc <- nabs_event_study(mydata, ..., method = "MC")Or call estimators directly and tidy their output:
fit <- DIDmultiplegtDYN::did_multiplegt_dyn(
df = mydata, outcome = "y", group = "id", time = "t",
treatment = "d", effects = 9, placebo = 6
)
tidy_dcdh <- as_nabs_event_study(fit, outcome = "y")
# Naive TWFE reference for the plot:
ref <- naive_twfe(mydata, outcome = "y", treatment = "d",
unit = "id", time = "t",
lags = 6, leads = 8)
# Overlay everything:
nabs_event_plot(
res_dcdh$tidy, res_pm$tidy, res_ife$tidy,
reference = ref,
xlim = c(-6, 8), ylim = c(-2, 2),
ylab = "Effect on outcome"
)nabs_event_plot() offers two ways to encode the pre/post
distinction, plus an option to join point estimates with a thin line.
Both arguments also flow through nabs_event_study_simple()
via ....
By default (style = "prepost_color"), each method gets
its own color with separate shades for pre- and post-treatment
periods:
nabs_event_plot(res_dcdh$tidy, res_pm$tidy, res_ife$tidy, reference = ref)With style = "method_shape", color encodes the
method only, and the pre/post distinction is carried by the
marker shape (hollow circles for pre, filled triangles for post). This
reads cleanly in grayscale:
nabs_event_plot(res_dcdh$tidy, res_pm$tidy, res_ife$tidy, reference = ref,
style = "method_shape")Set connect = TRUE (works with either style) to join
each series’ point estimates with a thin line, drawn through the full
path (pre and post are connected, including across the treatment
boundary):
nabs_event_plot(res_dcdh$tidy, res_pm$tidy, res_ife$tidy, reference = ref,
style = "method_shape", connect = TRUE)If you have already run supported estimators, you can convert their
result objects into the common nabs_event_study_tbl schema
with as_nabs_event_study().
tidy_one <- as_nabs_event_study(fit_dcdh, outcome = "y")
tidy_all <- as_nabs_event_study(
list(fit_dcdh, fit_panelmatch, fit_ife),
outcome = "y"
)Results returned by nabs_event_study() and
nabs_event_study_simple() can also be passed back to
as_nabs_event_study():
res <- nabs_event_study(...)
tidy_res <- as_nabs_event_study(res)
res_simple <- nabs_event_study_simple(...)
tidy_simple <- as_nabs_event_study(res_simple)All tidiers return a tibble of class
nabs_event_study_tbl with these columns:
| column | type | description |
|---|---|---|
time |
int | Relative period (0 = treatment onset/switch). |
estimate |
num | Point estimate. |
std.error |
num | Standard error (may be NA). |
conf.low |
num | Lower CI bound. |
conf.high |
num | Upper CI bound. |
window |
chr | "pre" if time < 0, else
"post". |
method |
chr | "DCDH", "PanelMatch", "IFE",
"FE", "MC", "TWFE", … |
outcome |
chr | Outcome variable name. |
All methods share this convention (time = 0 = treatment onset / the
period of a treatment switch, time = -1 = reference). DCDH’s native
output anchors the reference at 0, so it is shifted by one
period internally to line up.
Anything coercible to a data frame with at least time
and estimate columns also flows through
as_nabs_event_study(). Adding a new estimator later means
writing a one-line method that pulls the right slots — the plotting code
keeps working.
This package is experimental. The output schema is intended to be stable, but the upstream estimator packages occasionally rearrange their internal structures, so please pin versions in production code.
If you use nonabsdid in your work, please kindly cite
the package:
Takuma Iwasaki (2026). nonabsdid: Heterogeneity-Robust DID Event Studies with Non-Absorbing Binary Treatments. R package version X.Y.Z. https://github.com/takuma1102/nonabsdid
Please also cite whichever underlying estimator(s) you actually used.