The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
This vignette documents how fetwfe(),
betwfe(), etwfe(), and twfeCovs()
compute their standard errors, what assumptions those standard errors
rely on, and how to opt into an experimental unit-clustered
alternative when the default assumptions look restrictive. The four
estimators share the same inferential machinery, so the discussion
applies to all of them; we use fetwfe() in the running
example.
att_se and catt_ses are under
Assumption F1By default, the package’s standard errors — the att_se
slot on the returned object and the entries of catt_ses —
are computed under paper Assumption F1 (Faletto 2025, arXiv:2312.05985). In words,
F1 says:
sig_eps_c_sq) but assumes no
within-unit serial correlation beyond that random effect, and
the idiosyncratic variance
(estimated as sig_eps_sq) is the same across units.Under F1, the regression-coefficient covariance contribution to the ATT standard error is
where
is the Gram inverse on the bridge-selected support and
encodes the cohort-weighted ATT contrast. The cohort-specific SEs
(catt_ses) have the same form with a cohort selector
in place of
.
The overall ATT carries a second variance term, , that comes from estimating the cohort-membership probabilities . This term scales like and is unrelated to the regression residuals.
indep_counts, the package treats the
cohort-membership counts as coming from an independent split, so the two
variance terms simply add:
is asymptotically exact.indep_counts is omitted (the common case), the
package returns the conservative Cauchy-Schwarz bound
,
which is valid under any covariance between the two pieces.Either way, the standard error printed and stored on the object is the square root of this combined variance.
Assumption F1 is the workhorse setting in the paper and it is well-suited to the asymptotic theory underpinning Theorems 6.1–6.3. In applied DiD work, however, it is not unusual to suspect one or more of the following violations:
The unit random effect in F1 absorbs a single, time-constant deviation per unit. It does not model serial correlation in the idiosyncratic shocks: under F1, and are uncorrelated once is conditioned on. In practice, panel outcomes often exhibit residual time-series structure (mean reversion, lagged shocks, sticky deviations) that the random effect alone cannot explain. Bertrand, Duflo, and Mullainathan (2004) is the classic warning that ignoring within-unit serial correlation can drastically understate DiD standard errors.
F1 imposes a single across all units. If the residual variance differs across, say, large vs. small states, or volatile vs. stable industries, the model-based variance can be off in either direction relative to a heteroskedasticity-robust alternative.
F1 treats units as i.i.d. If observations within a state-year, industry-year, or other higher-level grouping share unobserved shocks across multiple sampled units, the variance estimated under F1 will understate the true sampling variability. The package’s current data model does not target this case directly: the natural opt-in cluster level (which is the level the experimental option below uses) is the unit itself.
In all three cases, a textbook fix is to replace the model-based variance with a sandwich estimator that does not rely on the compound-symmetric covariance structure.
se_type = "cluster"Starting in version 1.6.0, all four estimators
(fetwfe(), betwfe(), etwfe(),
twfeCovs()) and their *WithSimulatedData()
wrappers accept an experimental se_type argument:
Setting se_type = "cluster" swaps the model-based
regression-coefficient variance
for a unit-clustered Liang-Zeger CR1 sandwich computed
on the bridge-selected support. The default
(se_type = "default") is unchanged.
Let be the support selected by the bridge regression, the corresponding design matrix in the coordinate system the regression was solved in (GLS-transformed for ETWFE/twfeCovs, fusion-then-GLS-transformed for FETWFE/BETWFE), and the residuals from OLS on that selected support. The cluster-robust variance is
with units
as clusters and an
small-sample adjustment (matching
sandwich::vcovCL(cadjust = TRUE, type = "HC0")). The CATT
SE for cohort
is
(using a zero-padded
on the full selected support); the ATT regression-coefficient variance
is
,
replacing
above. The second variance term
(from estimating cohort probabilities) is unchanged because it depends
on empirical cohort proportions, not regression residuals; the
conservative-vs-asymptotically-exact combination logic also carries
through unchanged.
For FETWFE and BETWFE, se_type = "cluster" is only
meaningful when q < 1 (the bridge oracle property is
required); for q >= 1 the cluster path returns
NA just like the default. ETWFE and twfeCovs
have no q argument, so the cluster path always runs when
the Gram matrix is invertible.
The CR1 sandwich is a textbook estimator and the package’s
implementation matches sandwich::vcovCL() to numerical
precision on a clean panel without selection. What is not yet
covered by the paper’s theory is:
These extensions are mechanically routine but conceptually
non-trivial, and they are explicitly outside the package’s current
scope. Until they land, se_type = "cluster" is exposed as
an opt-in, clearly-labelled experimental feature.
Recommendation. Until the theory lands, treat
se_type = "cluster" as a sensitivity check: report both
se_type = "default" and se_type = "cluster" in
applied work, comment on the gap, and lean on the default for headline
numbers.
set.seed(2026)
sim_coefs <- genCoefs(R = 3, T = 6, d = 2, density = 0.5, eff_size = 2)
sim_data <- simulateData(
sim_coefs,
N = 120,
sig_eps_sq = 1,
sig_eps_c_sq = 0.5
)
res_default <- fetwfeWithSimulatedData(sim_data)
res_cluster <- fetwfeWithSimulatedData(sim_data, se_type = "cluster")
c(
default = res_default$att_se,
cluster = res_cluster$att_se
)
#> default cluster
#> 0.03444904 0.03576436On this F1-conforming simulated panel the two SEs are similar by construction: the data-generating process satisfies F1, so the model-based SE is already valid and the cluster-robust SE estimates the same underlying variance. Under a deliberately serially-correlated DGP (or under heteroskedasticity, or higher-level clustering) the cluster-robust SE will typically be larger.
The print() and summary() methods label the
SE so it is clear which one was used:
print(res_cluster)
#> Fused Extended Two-Way Fixed Effects Results
#> ===========================================
#>
#> Overall Average Treatment Effect (ATT):
#> Estimate: -0.2148
#> Std. Error (cluster-robust): 0.0358
#> P-value: 1.894e-09
#> Selected: TRUE
#> 95% CI: [-0.2849, -0.1447]
#>
#> Cohort Average Treatment Effects (CATT):
#> Cohort Estimated TE SE ConfIntLow ConfIntHigh P_value selected
#> 2 0.0000000 0.00000000 0.0000000 0.0000000 NA FALSE
#> 3 -0.5370618 0.05389132 -0.6426869 -0.4314368 2.15468e-23 TRUE
#> 4 0.0000000 0.00000000 0.0000000 0.0000000 NA FALSE
#>
#> Model Details:
#> Units (N) : 120
#> Time periods (T) : 6
#> Treated cohorts (R) : 3
#> Covariates (d) : 2
#> Features (p) : 62
#> Selected size : 16
#> Lambda* : 0.0925The CATT SEs and confidence intervals in catt_df are
recomputed from the same cluster-robust sandwich; the CATT p-values
follow accordingly.
Bertrand, M., Duflo, E., & Mullainathan, S. (2004). “How much should we trust differences-in-differences estimates?” Quarterly Journal of Economics 119(1), 249–275.
Faletto, G. (2025). “Fused Extended Two-Way Fixed Effects for Difference-in-Differences with Staggered Adoptions.” arXiv preprint arXiv:2312.05985.
Liang, K.-Y., & Zeger, S. L. (1986). “Longitudinal data analysis using generalized linear models.” Biometrika 73(1), 13–22.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.