Skip to content

Counterfactual estimators for panel data: sp.fect

sp.fect is a native port of the estimation core of Liu, Wang and Xu's fect (R; Stata port fect_stata): impute the untreated potential outcome of every treated unit-period from a model fitted on the untreated cells only, and average Y - Y(0) over the treated cells. It handles staggered adoption, many treated units, unbalanced panels and treatment reversals, and offers three outcome models.

import statspai as sp

fe  = sp.fect(df, y="y", treat="d", unit="id", time="t")                     # two-way FE (imputation)
ife = sp.fect(df, y="y", treat="d", unit="id", time="t", method="ife", r=2)  # interactive FE, 2 factors
mc  = sp.fect(df, y="y", treat="d", unit="id", time="t", method="mc", lam=0.01)  # matrix completion

ife.estimate                 # ATT over treated observations
ife.detail                   # by relative period: fect_time, relative_time, att, count
ife.model_info["pre_treatment_rmse"]   # fit on the untreated periods of treated units
ife_se = sp.fect(df, y="y", treat="d", unit="id", time="t", method="ife", r=2,
                 vce="bootstrap", n_boot=200, seed=0)   # unit bootstrap SEs

fect_time follows fect's coding (0 = last untreated period, 1 = first treated period); relative_time = fect_time - 1 is the StatsPAI convention shared with sp.callaway_santanna and sp.sun_abraham.

Choosing the outcome model

Model When Tuning
fe Parallel trends in the two-way sense are credible; equals sp.did_imputation on a staggered panel without reversals. none (min_t0 = 1)
ife Units respond differently to common shocks (a factor structure); the pre-treatment ATT path under fe is not flat. r factors (min_t0 = 5)
mc Many treated cells, low-rank counterfactual with a soft penalty rather than a fixed rank. lam on fect's raw scale; model_info["lambda_norm"] reports it relative to the largest singular value, and a value above 1 collapses to fe

Cross-validation of r and lam is not ported; compare pre_treatment_rmse across candidates and read the pre-period ATT path.

Conventions and parity

The port runs fect's EM map step for step (fixest two-way initial fit, E-step fill of the treated cells, two-way demeaning, panel_factor SVD with the sqrt(T)/sqrt(N) normalisation or the soft-threshold on E/(T*N), relative convergence on the fitted surface and on the interactive component). Track A module 86 pins fe / ife / mc on one staggered two-factor panel against R fect at 1e-10 (same iteration count on both sides) and against the authors' Stata port at 1e-9 for fe / mc and 1.5e-7 for ife, where the Stata port's own stopping rule sets the floor.

Reference: Liu, Wang and Xu (2024), American Journal of Political Science 68(1), 160--176, liu2024practical.