Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
1933332
feat(C++): warm-start support in fe_ad_inter_iter / inter_fe_ub / int…
xuyiqing May 1, 2026
b23e856
feat(R): forward fit.init through fect_fe / fect_mc to C++ solvers
xuyiqing May 1, 2026
c738220
fix(diagtest): reword "F-test Failed" to "could not be computed"
xuyiqing May 1, 2026
5fdc1de
feat(estimand): add ci.method bc + normal; per-type defaults; nboots=…
xuyiqing May 1, 2026
4ac2b95
feat(estimand): hard-error on bootstrap cell-drop pathology in log.at…
xuyiqing May 1, 2026
7b34df7
test: ci.method bc + normal + per-type defaults + cell-drop hard-error
xuyiqing May 1, 2026
c51362f
fix(parallel): silence "package built under R version" warnings from …
xuyiqing May 1, 2026
b31e1d2
test: update H3 nboots default expectation 200 -> 1000
xuyiqing May 1, 2026
7319e92
release v2.4.2 prep: NEWS + bb-updates + DESCRIPTION + man + ARCHITEC…
xuyiqing May 1, 2026
8fd9f5f
Merge pull request #133 from xuyiqing/feat/v242-inference-infra
xuyiqing May 1, 2026
9736120
fix(vignette): bump 03-estimands setup-estimand DGP to keep Y safely …
xuyiqing May 1, 2026
0ec662c
feat(estimand): test = placebo / carryover argument (closes #131)
xuyiqing May 1, 2026
6641af7
feat(estimand+vartype): BCa CI + wild bootstrap + log.att hard-stop (…
xuyiqing May 1, 2026
64ff959
fix(tests+vignettes): align v2.4.2 expected hard-error message; sourc…
xuyiqing May 1, 2026
b4e9fbf
fix(estimand): location-shift parametric bootstrap before non-normal …
xuyiqing May 1, 2026
b786b69
docs(book): add ch9 "Bootstrap Inference Internals"; renumber 09→10, …
xuyiqing May 1, 2026
ff2c1d8
fix(estimand): support jackknife fits via slot-contract relaxation; h…
xuyiqing May 1, 2026
2df98f8
builder: wild bootstrap fix — perturb all observed cells (Option A)
xuyiqing May 1, 2026
731866e
test(wild): coverage + width-parity tests for the wild bootstrap fix
xuyiqing May 1, 2026
2742491
Revert "test(wild): coverage + width-parity tests for the wild bootst…
xuyiqing May 1, 2026
cdec373
Revert "builder: wild bootstrap fix — perturb all observed cells (Opt…
xuyiqing May 1, 2026
b9881ed
builder: add para.error arg — fold wild into parametric bootstrap
xuyiqing May 1, 2026
008f79a
WIP: test-para-error-full.R for wild-as-paraerror redesign (800 lines)
xuyiqing May 2, 2026
0104f8c
cleanup: remove unshipped vartype="wild" alias; expose para.error as …
xuyiqing May 2, 2026
d561e2a
test: fix coverage DGP (FIXED id_tr) + move slow simulations to tests…
xuyiqing May 2, 2026
6909fc0
fect(): clearer error when vartype="parametric" meets default time.co…
xuyiqing May 2, 2026
e45a852
docs(book): restructure Quarto book into 4 parts; reorder chapters by…
xuyiqing May 2, 2026
fcdf0bd
fect(): move parametric-nevertreated gate after reversal-check; prese…
xuyiqing May 2, 2026
59a5787
docs(book): finish e45a852 (YAML parts + index Organization) + Phase …
xuyiqing May 2, 2026
649ea15
docs(book): Phase B inference chapter rewrite
xuyiqing May 2, 2026
de1a96d
fix(docs): codoc WARNING in fect.Rd + simplify NEWS v2.4.2 + .gitigno…
xuyiqing May 2, 2026
2a53cc8
docs: simplify bb-updates v2.4.2 to hierarchical bullets; drop warm-s…
xuyiqing May 2, 2026
a1eeaf8
docs(book): make bb-updates a numbered chapter so @sec-changelog cros…
xuyiqing May 2, 2026
2598619
test(scaffold): partial warm-start Phase B/B-CFE validation script
xuyiqing May 2, 2026
3dc2e94
docs(book): rename ch7 + cc-references; simplify version-check chunk
xuyiqing May 2, 2026
50d595f
docs(book): unlabel Changelog + simplify v2.4.2 to chapter pointers
xuyiqing May 2, 2026
dc2fc71
feat(defaults): tighten EM tol + max.iteration; add convergence warning
xuyiqing May 3, 2026
5c10908
feat(cfe): bring dormant fit_init plumbing to v2.4.2 (matches NEWS cl…
xuyiqing May 3, 2026
2f52693
docs(v2.4.2): bb-updates tol-fix bullet + ARCHITECTURE manual patch
xuyiqing May 3, 2026
d2a0d81
test(coverage-study): bump fect_para cores 4 -> 10 in run_para_error_…
xuyiqing May 3, 2026
6a9425a
feat(inference): nboots = 200 default + tail-CI under-replication war…
xuyiqing May 3, 2026
58af92a
test(prune): trim test-factors-from-refactor.R (-11 tests, -178 lines)
xuyiqing May 3, 2026
f7c1dcd
test(refactor): split test-score-unify.R into 6 files + shared helper
xuyiqing May 3, 2026
1ac0e0c
v2.4.2 polish: estimand CI fallbacks + att.cumu basic + ch2/ch7 restr…
xuyiqing May 4, 2026
e65be95
test(coverage-study): add minimal_coverage suite + tail-CI rerun + re…
xuyiqing May 4, 2026
20f22a8
docs(ch7): rewrite "Empirical coverage" with minimal coverage results
xuyiqing May 4, 2026
a2cf513
docs(ch7): correct nboots default + restructure decision tree + drop …
xuyiqing May 4, 2026
055552e
v2.4.2: ci.method API on fect() + parametric basic location-shift
xuyiqing May 4, 2026
6704df1
fix(cran): drop non-ASCII chars in R/default.R + bump Date
xuyiqing May 4, 2026
7c0ca82
v2.4.2 polish: warnings cleanup, vignette wording, rscript renumber
xuyiqing May 5, 2026
0256515
Merge pull request #136 from xuyiqing/feat/v242-completion
xuyiqing May 5, 2026
b684d77
v2.4.3: fix quiet_nonpara closure leak in parallel bootstrap (#137)
xuyiqing May 15, 2026
e69bdfb
v2.4.4 feat: $sample slot + $data.long for panelview(fit) (#138)
xuyiqing May 20, 2026
96a74d7
v2.4.5: group.fe for sub-group treatment + CFE force fix + API hygien…
xuyiqing May 22, 2026
5922dd8
CRAN prep: minimal test file; drop legacy pkgdown tooling
xuyiqing May 29, 2026
33fab60
docs(book): sync user-manual version refs to 2.4.5 CRAN release
xuyiqing May 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@
^data-raw$
^cell-D1\.rds$
^fect_.*\.tar\.gz$
^fect\.Rcheck$
^fect\.Rcheck$
^tests/coverage-study$
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ vignettes/*.html
vignettes/*.pdf
vignettes/*_cache/
vignettes/*_files/
vignettes/*.rmarkdown
vignettes/site_libs/
vignettes/.quarto/
vignettes/_back/**
vignettes/_book/**
!vignettes/_book/rscript/
Expand Down
20 changes: 12 additions & 8 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
# Architecture — fect

> Generated by scriber for run `2026-04-30-architecture-regen-v241` on 2026-04-30.
> Manual v2.4.2 patches applied 2026-05-01 (warm-start C++ infrastructure;
> ci.method extensions) and 2026-05-02 (CFE `fit_init` plumbing on
> `complex_fe_ub` + `cfe_iter`, dormant). Full regen via scriber
> deferred until next material module change.

## Overview

fect is an R package for estimating causal effects in panel data using counterfactual imputation methods (Fixed Effects Counterfactual Estimators). It targets causal panel analysis with binary treatments under the parallel trends assumption, supporting treatment switching and limited carryover effects. The core abstraction is counterfactual imputation: impute missing potential outcomes Y(0) for treated units using control units, then compute the Average Treatment Effect on the Treated (ATT) as the gap between observed and imputed outcomes. The package is an R/C++ hybrid using Rcpp and RcppArmadillo for numerically intensive linear algebra (SVD, EM iterations, matrix factorization). Key external dependencies include fixest (initial FE regression), ggplot2 (visualization), doParallel/doFuture/future.apply (parallel bootstrap), MASS (generalized inverse), and mvtnorm (multivariate normal draws). Estimation methods include FE (fixed effects), IFE (interactive fixed effects / factor model), MC (matrix completion via nuclear norm regularization), CFE (complex fixed effects with structured covariates), and wrappers for modern DID estimators. Version 2.4.1. References: Liu, Wang, and Xu (2024); Chiu et al. (2026).
fect is an R package for estimating causal effects in panel data using counterfactual imputation methods (Fixed Effects Counterfactual Estimators). It targets causal panel analysis with binary treatments under the parallel trends assumption, supporting treatment switching and limited carryover effects. The core abstraction is counterfactual imputation: impute missing potential outcomes Y(0) for treated units using control units, then compute the Average Treatment Effect on the Treated (ATT) as the gap between observed and imputed outcomes. The package is an R/C++ hybrid using Rcpp and RcppArmadillo for numerically intensive linear algebra (SVD, EM iterations, matrix factorization). Key external dependencies include fixest (initial FE regression), ggplot2 (visualization), doParallel/doFuture/future.apply (parallel bootstrap), MASS (generalized inverse), and mvtnorm (multivariate normal draws). Estimation methods include FE (fixed effects), IFE (interactive fixed effects / factor model), MC (matrix completion via nuclear norm regularization), CFE (complex fixed effects with structured covariates), and wrappers for modern DID estimators. Version 2.4.2. References: Liu, Wang, and Xu (2024); Chiu et al. (2026).

---

Expand Down Expand Up @@ -121,7 +125,7 @@ graph TD
| `R/interFE.R` (515 lines) | API | Standalone interactive fixed effects estimator | `interFE()` | no |
| `R/did_wrapper.R` (656 lines) | API | Modern DID estimator wrappers (did, DIDmultiplegtDYN) | `did_wrapper()` | no |
| `R/fect_mspe.R` (370 lines) | API | MSPE computation for model comparison | `fect_mspe()` | no |
| `R/po-estimands.R` (1,123 lines) | API | Two-tier post-hoc estimand surface: long-form imputed PO accessor and typed dispatcher; `vartype` enum extended to `"parametric"` in v2.4.1 | `estimand()`, `imputed_outcomes()` | yes (new v2.4.0) |
| `R/po-estimands.R` (1,236 lines) | API | Two-tier post-hoc estimand surface: long-form imputed PO accessor and typed dispatcher; `vartype` enum extended to `"parametric"` in v2.4.1; `ci.method` enum extended to `c("basic","percentile","bc","normal")` with per-type defaults via NULL trigger in v2.4.2; hard-error on bootstrap cell-drop pathology in `log.att`/`aptt` | `estimand()`, `imputed_outcomes()` | yes |
| `R/fe.R` (955 lines) | Estimation | Interactive Fixed Effects / factor model estimation | `fect_fe()` | no |
| `R/mc.R` (807 lines) | Estimation | Matrix Completion via nuclear norm regularization | `fect_mc()` | no |
| `R/cfe.R` (1,173 lines) | Estimation | Complex Fixed Effects with structured covariates | `fect_cfe()` | no |
Expand Down Expand Up @@ -155,8 +159,8 @@ graph TD
| `src/ife.cpp` (534 lines) | C++ Core | IFE algorithm: `inter_fe()`, `inter_fe_ub()`, `inter_fe_d()` | (Rcpp exports) | no |
| `src/ife_sub.cpp` (577 lines) | C++ Core | IFE sub-routines: SVD factor estimation, EM iterations, alternating minimization | (internal) | no |
| `src/mc.cpp` (223 lines) | C++ Core | Matrix completion: `inter_fe_mc()`, nuclear norm penalization | (Rcpp exports) | no |
| `src/cfe.cpp` (203 lines) | C++ Core | Complex FE: `complex_fe_ub()` | (Rcpp exports) | no |
| `src/cfe_sub.cpp` (564 lines) | C++ Core | Complex FE sub-routines: `cfe_iter()`, structured covariate handling | (internal) | no |
| `src/cfe.cpp` (203 lines) | C++ Core | Complex FE: `complex_fe_ub()`. v2.4.2: optional `fit_init` matrix to seed EM (dormant; mirrors IFE/MC infra) | (Rcpp exports) | no |
| `src/cfe_sub.cpp` (564 lines) | C++ Core | Complex FE sub-routines: `cfe_iter()`, structured covariate handling. v2.4.2: optional `fit_init` matrix replaces default `fit = Y0` initialization (dormant) | (internal) | no |
| `src/fe_sub.cpp` (291 lines) | C++ Core | Shared FE utilities: `Y_demean()`, `panel_beta()`, `panel_factor()`, `panel_FE()`, `XXinv()` | (internal) | no |
| `src/binary_sub.cpp` (539 lines) | C++ Core | Probit model sub-routines for binary outcomes | (internal) | no |
| `src/binary_qr.cpp` (347 lines) | C++ Core | QR-based probit estimation | (internal) | no |
Expand Down Expand Up @@ -268,8 +272,8 @@ graph TD
| `fect.default()` | `R/default.R` | `fect.formula()`, user | `fect_cv()`, `fect_fe()`, `fect_mc()`, `fect_cfe()`, `fect_boot()`, `diagtest()` | yes | Workhorse: validation, preprocessing, method routing, inference, diagnostics; added `W.est`/`W.agg`/`carryover.rm` |
| `fect_fe()` | `R/fe.R` | `fect.default()`, `fect_cv()`, `fect_boot()`, `r.cv.rolling()` | `inter_fe_ub()`, `inter_fe_d_qr_ub()` (C++) | no | IFE estimation (factor model with r latent factors) |
| `fect_mc()` | `R/mc.R` | `fect.default()`, `fect_cv()`, `fect_boot()` | `inter_fe_mc()` (C++) | no | Matrix completion estimation (nuclear norm regularization) |
| `fect_cfe()` | `R/cfe.R` | `fect.default()`, `fect_boot()`, `r.cv.rolling()` | `complex_fe_ub()` (C++) | no | Complex FE with structured covariates (Z, Q, gamma, kappa) |
| `fect_nevertreated()` | `R/fect_nevertreated.R` | `fect.default()` | `fect_fe()`, `fect_mc()`, `fect_cfe()`, `.fect_make_future_cluster()` | yes | Wrapper for never-treated-only estimation sample; PSOCK cluster via shared helper (v2.3.3) |
| `fect_cfe()` | `R/cfe.R` | `fect.default()`, `fect_boot()`, `r.cv.rolling()` | `complex_fe_ub()` (C++) | no | Complex FE with structured covariates (Z, Q, gamma, kappa); v2.4.2 dormant `fit.init = NULL` parameter threaded through to C++ |
| `fect_nevertreated()` | `R/fect_nevertreated.R` | `fect.default()` | `fect_fe()`, `fect_mc()`, `fect_cfe()`, `.fect_make_future_cluster()` | yes | Wrapper for never-treated-only estimation sample; PSOCK cluster via shared helper (v2.3.3); v2.4.2 dormant `fit.init = NULL` parameter, sliced to control units |
| `fect_cv()` | `R/cv.R` | `fect.default()` | `fect_fe()`, `fect_mc()`, `.fect_apply_cv_rule()`, `.fect_cv_aggregate_folds()` | yes | Cross-validation to select r (IFE) or lambda (MC); rolling default (v2.3.0), 1-SE rule (v2.3.0) |
| `r.cv.rolling()` | `R/cv-rolling.R` | user / exported | `fect_fe()`, `fect_cfe()`, `.fect_apply_cv_rule()`, `.fect_make_future_cluster()` | yes (new v2.3.0) | Standalone rolling-window CV for rank selection; per-fold unit sampling; closes AR forward-leakage |
| `fect_boot()` | `R/boot.R` | `fect.default()` | `fect_fe()`, `fect_mc()`, `fect_cfe()`, `impute_Y0()`, `valid_controls()`, `.fect_make_future_cluster()` | yes | Bootstrap/jackknife/parametric inference with PSOCK retry-with-backoff (v2.3.3) |
Expand All @@ -279,7 +283,7 @@ graph TD
| `did_wrapper()` | `R/did_wrapper.R` | user / exported | `fixest::feols()`, `did::att_gt()` | no | Modern DID estimator wrappers |
| `plot.fect()` | `R/plot.R` | user / exported | ggplot2, `.modern_theme()` | yes | 14 plot types; modernized defaults, `legacy.style`/`highlight`/`highlight.fill` (v2.3.2) |
| `esplot()` | `R/esplot.R` | user / exported | ggplot2, `.modern_theme()` | yes | Standalone event-study plot; modern theme integration (v2.3.2) |
| `estimand()` | `R/po-estimands.R` | user / exported (new v2.4.0) | `imputed_outcomes()`, internal aggregators | yes (new v2.4.0) | Typed dispatcher: `att`, `att.cumu`, `aptt`, `log.att` across `event.time`/`cohort`/`calendar.time`/`overall`; `vartype` enum extended to `"parametric"` in v2.4.1 |
| `estimand()` | `R/po-estimands.R` | user / exported (new v2.4.0) | `imputed_outcomes()`, internal aggregators, `.compute_ci()` | yes | Typed dispatcher: `att`, `att.cumu`, `aptt`, `log.att` across `event.time`/`cohort`/`calendar.time`/`overall`; `vartype` enum extended to `"parametric"` in v2.4.1; `ci.method` enum extended to `c("basic","percentile","bc","normal")` with per-type defaults via NULL trigger in v2.4.2 |
| `imputed_outcomes()` | `R/po-estimands.R` | user / exported (new v2.4.0); `estimand()` | internal helpers | yes (new v2.4.0) | Long-form accessor for cell-level imputed PO surface; `cells =` filter (logical / formula); `direction = c("on", "off")`; `eff_debias` slot support |
| `effect()` | `R/effect.R` | user / exported | (internal helpers) | yes (soft-deprecated v2.4.0) | Treatment effect decomposition; emits one-time-per-session deprecation message: *"`effect()` is soft-deprecated as of fect 2.4.0; prefer `estimand(fit, "att.cumu", ...)` API."* Removal not before v3.0.0 |
| `att.cumu()` | `R/cumu.R` | user / exported | (internal helpers) | yes (soft-deprecated v2.4.0, `n_cells` fix v2.4.1) | Cumulative ATT; emits same one-time deprecation; `n_cells` column fixed in v2.4.1 |
Expand All @@ -290,7 +294,7 @@ graph TD
| `diagtest()` | `R/diagtest.R` | `fect.default()` | — | yes | Pre-trend, placebo, carryover, equivalence tests; `drop=FALSE` guard (v2.3.3) |
| `inter_fe_ub()` | `src/ife.cpp` | `fect_fe()` | `panel_factor()`, `fe_ub()`, `Y_demean()` | no | C++ IFE with unbalanced panels (EM algorithm) |
| `inter_fe_mc()` | `src/mc.cpp` | `fect_mc()` | `panel_FE()`, `Y_demean()` | no | C++ matrix completion with nuclear norm |
| `complex_fe_ub()` | `src/cfe.cpp` | `fect_cfe()` | `cfe_iter()`, `Y_demean()` | no | C++ complex FE estimation |
| `complex_fe_ub()` | `src/cfe.cpp` | `fect_cfe()` | `cfe_iter()`, `Y_demean()` | no | C++ complex FE estimation; v2.4.2 optional `fit_init` parameter (NULL default = byte-identical to pre-v2.4.2) |
| `panel_factor()` | `src/fe_sub.cpp` | `inter_fe_ub()`, others | SVD routines | no | Extract latent factors via SVD |
| `panel_FE()` | `src/fe_sub.cpp` | `inter_fe_mc()`, others | soft-thresholding | no | Nuclear norm regularization / soft-thresholding |
| `Y_demean()` | `src/fe_sub.cpp` | most C++ estimators | (arma operations) | no | Remove unit and/or time fixed effects |
Expand Down
18 changes: 9 additions & 9 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
Package: fect
Type: Package
Title: Fixed Effects Counterfactual Estimators
Version: 2.4.1
Date: 2026-04-29
Version: 2.4.5
Date: 2026-05-29
Authors@R:
c(person("Licheng", "Liu", , "lichengl@stanford.edu", role = c("aut")),
c(person("Yiqing", "Xu", , "yiqingxu@stanford.edu", role = c("aut", "cre")),
person("Licheng", "Liu", , "lichengl@stanford.edu", role = c("aut")),
person("Ziyi", "Liu", , "zyliu2023@berkeley.edu", role = c("aut")),
person("Ye", "Wang", , "yezhehuzhi@gmail.com", role = c("aut")),
person("Yiqing", "Xu", , "yiqingxu@stanford.edu", role = c("aut", "cre")),
person("Ye", "Wang", , "yezhehuzhi@gmail.com", role = c("aut")),
person("Tianzhu", "Qin", , "tianzhu@stanford.edu", role = c("aut")),
person("Shiyun", "Hu", , "hushiyun@pku.edu.cn", role = c("aut")),
person("Rivka", "Lipkovitz", , "rivkal@mit.edu", role = c("aut")))
Author: Licheng Liu [aut], Ziyi Liu [aut], Ye Wang [aut], Yiqing Xu [aut, cre],
Tianzhu Qin [aut], Shiyun Hu [aut], Rivka Lipkovitz [aut]
Author: Yiqing Xu [aut, cre], Licheng Liu [aut], Ziyi Liu [aut], Ye Wang [aut], Tianzhu Qin [aut], Shiyun Hu [aut], Rivka Lipkovitz [aut]
Maintainer: Yiqing Xu <yiqingxu@stanford.edu>
Description: Provides tools for estimating causal effects in panel data using counterfactual methods, as well as other modern DID estimators. It is designed for causal panel analysis with binary treatments under the parallel trends assumption. The package supports scenarios where treatments can switch on and off and allows for limited carryover effects. It includes several imputation estimators, such as Gsynth (Xu 2017), linear factor models, and the matrix completion method. Detailed methodology is described in Liu, Wang, and Xu (2024) <doi:10.48550/arXiv.2107.00856> and Chiu et al. (2025) <doi:10.48550/arXiv.2309.15983>. Optionally integrates with the "HonestDiDFEct" package for sensitivity analyses compatible with imputation estimators. "HonestDiDFEct" is not on CRAN but can be obtained from <https://github.com/lzy318/HonestDiDFEct>.
URL: https://yiqingxu.org/packages/fect/, https://github.com/xuyiqing/fect
Expand Down Expand Up @@ -46,9 +45,10 @@ Suggests:
panelView,
testthat (>= 3.0.0),
did,
DIDmultiplegtDYN,
DIDmultiplegtDYN,
ggrepel,
HonestDiDFEct
HonestDiDFEct,
withr
Depends: R (>= 4.1.0)
LinkingTo: Rcpp, RcppArmadillo
RoxygenNote: 7.3.3
Expand Down
437 changes: 0 additions & 437 deletions NEWS.html

This file was deleted.

Loading
Loading