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 fe → cfe) |
✓ | – | – | – | ✓ |
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. |
"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
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).
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
cfeallows either “jackknife” or “bootstrap” for uncertainty estimates.Factor-based methods (
ife,gsynth) can userandkfor factor selection and cross-validation. We can implement a similar process usingmcorgsynthwithlambdaandnlambda.carryoverTestis available infe,ife,mc, andcfebut not ingsynth.loois available infe,ife,mc, andgsynth.The cfe method supports additional parameters:
Z/gammafor time-invariant covariates with time-varying coefficients,Q/kappa(orQ.type) for unit-specific time trends, extra additive fixed effects viaindex[3:], and interactive fixed effects viar. See Chapter 5 for details.forceallows 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, orCV) are set toFALSEby 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!