12  Cheatsheet

In this chapter, we provide an overview of the main functionalities of the fect package, including the required inputs, available plot types, key options, and testing capabilities across various methods.

12.1 Methods

Inputs for fect(methods = "___")

Method Model for \(\hat{Y}(0)\) References
fe Standard two-way fixed effects model Liu, Wang & Xu (2022), Borusyak, Jaravel & Spiess (2024)
ife Interactive fixed effects model Gobillon & Magnac (2016), Xu (2017)
mc Matrix completion method Athey et al. (2021)
cfe “Complex” or multi-level fixed effects
gsynth Interactive fixed effects model Xu (2017)

12.2 Plot Types

Inputs for plot(fect_object, type = "___")

Type Description Applicable Methods
box Box plot of ATT by period. fe, ife, mc, gsynth, cfe
calendar CATT by calendar time. fe, ife, mc, gsynth, cfe
heterogeneous or hte CATT by a covariate. fe, ife, mc, gsynth, cfe
counterfactual or ct Observed vs. imputed outcome for treated units. fe, ife, mc, gsynth
equiv Pretreatment residuals with equivalence intervals. fe, ife, mc, gsynth, cfe
exit Period-wise ATT relative to treatment exit. fe, ife, mc, cfe
factors Estimated factors (factor-based methods). ife, gsynth
gap or es Event-study plot: ATT by pre- and post-treatment periods. fe, ife, mc, gsynth, cfe
loadings Estimated factor loadings (factor-based methods). ife, gsynth
status Treatment status by period for all units. fe, ife, mc, gsynth, cfe
sens Rambachan & Roth (2023) sensitivity analysis for treatment effects. fect_sens() function applied to fe, ife, mc, gsynth, cfe
sens_es Event-study sensitivity analysis for treatment effects. fect_sens() function applied to fe, ife, mc, gsynth, cfe
cumul Cumulative treatment effects over time. estimand(fit, "att.cumu", "event.time"); see Chapter 3.

12.3 Tests as Options

Inputs for fect(...)

Input Description Applicable Methods
loo Leave-one-period-out goodness-of-fit test (TRUE/FALSE). fe, ife, mc, gsynth
carryoverTest Tests for carryover effects in post-treatment periods (TRUE/FALSE). fe, ife, mc, cfe
carryover.period Range of post-treatment periods for the carryover test (vector). fe, ife, mc, cfe
permute Permutation test (TRUE/FALSE). fe, ife, mc, gsynth
m Block length for permutation test (m=2 by default). fe, ife, mc, gsynth
CV Cross-validation for factor-based methods. ife, mc, gsynth

12.4 Required and Optional Inputs

A check mark (✓) indicates that the method requires or accepts the input.

12.4.1 Required Inputs

Input fe ife mc gsynth cfe
Y (outcome)
D (treatment)
X (covariates)
data
index (unit & time IDs)
group.fe (additional additive FEs; auto-routes fecfe)
cfe (complex / interactive FEs)
Z (time-invariant covariates)
Q (known time trends)
Q.type (auto time trends)

12.4.2 Optional Inputs

Input fe ife mc gsynth cfe
W (weight column; convenience default for both W.est and W.agg)
W.est (weight column for outcome-model fit only)
W.agg (weight column for ATT aggregation only)
time.component.from (time component source)
em (EM algorithm)
se (uncertainty)
nboots (# bootstrap reps)
force (FE structure)
lambda (Hyper-parameter sequence)
nlambda (Length of hyper-parameter sequence)
r (# factor)
k ( # cross-validation rounds)
gamma (time grouping for Z)
kappa (unit grouping for Q)
Z.param (Z block assignment)
Q.param (Q block assignment)
Q.bspline.degree (B-spline degree)

12.4.3 Important Options

Input Options Applicable Methods
force Fixed effects structure: “none”, “unit”, “time”, “two-way” (default) fe, ife, mc, cfe, gsynth
time.component.from Time component source: “notyettreated” (default), “nevertreated”. Controls which units provide the time-varying model components (time fixed effects, latent factors, temporal dynamics). When “nevertreated”, only never-treated controls estimate these components. method = "gsynth" auto-sets to “nevertreated”. ife, mc, cfe, gsynth
em EM algorithm: TRUE (default), FALSE. Required TRUE for “notyettreated”; auto-set to FALSE by method = "gsynth". ife, cfe
vartype (when method = "gsynth") Uncertainty estimator: “parametric” (default), “bootstrap”, “jackknife” gsynth
vartype (otherwise) Uncertainty estimator: “bootstrap” (default), “jackknife” fe, ife, mc, cfe
criterion Model selection criterion: “mspe” (default), “gmspe”, “moment”, “pc”. ife, mc, cfe, gsynth

12.5 Cross-Validation

Cross-validation in fect() selects the number of factors r (or the regularization lambda for MC) by minimizing held-out prediction error. As of v2.3.0, three masking strategies are exposed via cv.method:

12.5.1 Choosing the masking strategy

cv.method Mask design When to use
"rolling" (default) Per-fold sample of cv.prop of eligible units; per sampled unit a random anchor + cv.nobs scored holdout + cv.buffer past-side buffer + drop-future from anchor through end-of-eligible. Eligible units = controls + treated pre-treatment cells. The recommended default. Closes the future-side leakage channel that block CV cannot, eliminating the over-selection pathology that pegs r.cv = r.max on serially correlated panels.
"block" Random scattered anchors; mask cv.nobs contiguous cells per anchor; cv.donut cells flanking each side excluded from training but not scored. Eligible units = controls. Use under approximately i.i.d. residuals when forecast-style scoring is not needed.
"loo" Leave-one-out, one treated pre-treatment period at a time. Legacy gsynth method; can be unstable with few pre-treatment periods. Available for fect_nevertreated (time.component.from = "nevertreated") only.
WarningDeprecation: "all_units" and "treated_units"

Pre-v2.3.0 callers used cv.method = "all_units" (= the new "block") or cv.method = "treated_units" (block masking with anchors restricted to treated pre-treatment cells). Both names still work and produce identical numerical behavior, but they emit a one-time deprecation message and will be removed in v2.4.0. The replacement plan: keep cv.method = "block" as the masking strategy and introduce a separate cv.units parameter ("all" / "treated" / "control") for unit-scope selection. For now, replace "all_units" with "block" directly, and continue using "treated_units" until the cv.units parameter is available.

12.5.2 Sub-options (apply across "all_units", "treated_units", and "rolling" unless noted)

Option Default Applies to Description
k 20 all Number of CV folds
cv.prop 0.1 all For block: proportion of observations masked per round. For rolling: fraction of eligible units sampled per fold. The (k = 20, cv.prop = 0.1) pair gives ~2x coverage of every eligible unit across folds while keeping per-fold mask size moderate.
cv.nobs 3 all Block size for the held-out (scored) cells per anchor
cv.donut 1 block only Cells excluded around the holdout on each side, masked but not scored (attenuates AR leakage on both train/test boundaries; matches cv.buffer for rolling CV)
cv.buffer 1 rolling only Past-side buffer cells before the holdout, masked but not scored (the future side is dropped from training by construction)
cv.rule "1se" all Rule for picking r from the MSPE curve: "1se" (default; Hastie/Tibshirani/Friedman 2009 §7.10), "min", or "1pct" (pre-v2.3.0 default)
min.T0 5 all Minimum pre-treatment observations required per unit
seed NULL all Optional integer seed for reproducible per-fold mask sampling

12.5.3 Scoring criteria

The criterion parameter determines which metric is used to select the tuning parameter:

criterion Description When to use
"mspe" (default) Mean squared prediction error General-purpose; best for prediction accuracy
"gmspe" Geometric mean SPE Robust to outlier prediction errors
"pc" Information criterion (Bai & Ng) Penalized fit; does not require CV rounds
"moment" Weighted period-wise residual averages Selects for best pre-trend fit rather than prediction

12.5.4 Workflow

## Pick r via rolling CV (recommended)
fit_cv <- fect(Y ~ D, data = simdata, index = c("id", "time"),
               method = "ife", force = "two-way",
               CV = TRUE, r = c(0, 3),
               cv.method = "rolling",
               cv.buffer = 1, cv.nobs = 3, k = 20, cv.prop = 0.1,
               cv.rule = "1se", se = TRUE)
fit_cv$r.cv  # selected r

Block-CV variants are drop-in replacements: change cv.method to "all_units" or "treated_units" and replace cv.buffer with cv.donut (the buffer-parameter analog for block CV).

NoteWhy we prefer rolling CV: empirical evidence

When residuals are temporally correlated (post-fit residual AR(1) above ~0.4), block CV consistently over-selects r, often pegging at r.max. Rolling CV is the recommended choice in this regime; on approximately i.i.d. residuals the two designs agree closely.

Xu (2017) factor-model DGP, \(r_{\text{true}} = 2\), \(K = 200\) replications per cell, default settings:

Errors Rolling CV recovery Mean rolling r.cv Block CV recovery Mean block r.cv
iid (ρ = 0) 95.5% 1.96 88.0% 1.88
AR(1) ρ = 0.3 99.0% 1.99 88.5% 1.95
AR(1) ρ = 0.8 56.2% 1.58 15.0% 3.34

At ρ = 0.8, block CV picks r.cv ≥ 3 in 98.5% of IFE-EM reps and pegs at r.max = 5 in 17.5%; rolling CV picks r.cv ≥ 3 in only 4% and never pegs.

Rolling CV imposes essentially no penalty in the no-leakage regime and recovers the truth ~3.7× more often when leakage matters. Source script: code/sims/sim-cv-comparison-K200.R.

The standalone r.cv.rolling() helper exists for users who want the per-fold MSPE matrix and other diagnostics returned in addition to r.cv — but for normal use, the dispatcher path above is the recommended entry point.

12.6 Utility Functions

In addition to the main fect() function, the package provides several utility functions:

Function Description Key Arguments
esplot() Standalone event study plot from a data frame. Does not require a fect object. data, Period, Estimate, CI.lower, CI.upper, connected, highlight.periods
fect_mspe() Model comparison via cross-validated prediction error. Supports cv.method = "rolling" for AR-leakage-resistant scoring. out.fect, seed, cv.method, cv.buffer, criterion, k, cv.prop
r.cv.rolling() Standalone rolling-window CV for selecting r (number of factors). Recommended over block CV when residuals are serially correlated. Supports method ∈ {"ife", "gsynth", "cfe"}. formula, data, index, method, r.max, cv.nobs, cv.buffer, k, cv.prop, cv.rule, seed
get.cohort() Generate cohort indicators based on treatment timing. data, D, index, entry.time, start0
estimand() Unified post-hoc estimand dispatcher: per-event-time and overall ATT, cumulative ATT, APTT, log-ATT, with bootstrap or jackknife CIs. See Chapter 3. fit, type, by, cells, weights, window, direction, vartype, conf.level, ci.method
imputed_outcomes() Long-form accessor: cell-level imputed potential-outcome surface for custom estimands. fit, cells, replicates, direction
att.cumu() (Soft-deprecated; use estimand(fit, "att.cumu", "overall", window = ...).) Cumulative treatment effects over a specified period range. x, period, weighted, type
effect() (Soft-deprecated; use estimand(fit, "att.cumu", "event.time") or estimand(fit, "att", "event.time").) Cumulative or subgroup-averaged treatment effects; requires keep.sims = TRUE. x, cumu, id, period, plot

12.7 Notes

  • Most methods share core inputs (Y, D, X, data, index).

  • Method cfe allows either “jackknife” or “bootstrap” for uncertainty estimates.

  • Factor-based methods (ife, gsynth) can use r and k for factor selection and cross-validation. We can implement a similar process using mc or gsynth with lambda and nlambda.

  • carryoverTest is available in fe, ife, mc, and cfe but not in gsynth. loo is available in fe, ife, mc, and gsynth.

  • The cfe method supports additional parameters: Z/gamma for time-invariant covariates with time-varying coefficients, Q/kappa (or Q.type) for unit-specific time trends, extra additive fixed effects via index[3:], and interactive fixed effects via r. See Chapter 5 for details.

  • force allows various levels of fixed effects ("none", "unit", "time", "two-way").

  • fect includes several built-in values for optional arguments that often require an integer or boolean input. All boolean arguments (such as parallel, se, or CV) are set to FALSE by default to speed up computation. Below is a complementary table listing parameters that require numeric inputs.

Inputs Description Default
nboots Number of bootstrap runs (int) 200
k Sets the number of cross-validation rounds(int) 10
r Sets the number of factors 0; c(0,3) when CV
m Specifies the block length for the permutation test 2
nlambda Length of hyper-parameter sequence 10
  • With an integer input for nlambda, fect can randomly generate appropriate hyper-parameter sequence.

Enjoy using fect!