Linear regression with multiple high-dimensional fixed effects — in Stata, Python and R, on one fast C++ core.
Version 2.24.1 · License: MIT · Stata + Python + R · Optional CUDA GPU
xhdfe estimates linear models with any number of high-dimensional fixed
effects (HDFE) — the worker–firm, patent–inventor, and multi-way panel designs
common in applied economics. It mirrors the defaults and reporting of
reghdfe (Correia 2016): under the
default reghdfe-comparable tolerance mode, coefficients match reghdfe at the
same nominal tolerance. The same estimator is exposed through three front-ends —
a Stata command, a Python package, and an R package — all sitting on a single
compiled C++ core. CPU is the reference backend; an optional CUDA GPU absorber
is available for large problems.
The package also ships xfe (hence the repository name xhdfe-xfe), a
companion Stata command that partials out — residualizes — variables against
multiple high-dimensional fixed effects on the same core, without fitting a
regression. See Stata below and help xfe.
As an illustration, the table below reports median estimator-call runtimes for an AKM-style wage regression using Portuguese matched employer-employee data. The specification uses 55,947,171 observations and absorbs 5,948,793 worker, 799,265 firm, and 36 year fixed effects. It includes common seniority controls and clusters standard errors at the worker level:
| Implementation | Backend | Seconds | Speedup vs. reghdfe |
|---|---|---|---|
reghdfe, Stata |
CPU | 3,667.5 | 1.0x |
FixedEffectModels.jl |
CPU | 916.3 | 4.0x |
fixest |
CPU | 486.5 | 7.5x |
pyfixest |
CPU | 110.4 | 33.2x |
FixedEffectModels.jl |
CUDA | 105.7 | 34.7x |
xhdfe, Stata |
CPU | 61.3 | 59.8x |
xhdfe, Python |
CPU | 53.6 | 68.4x |
xhdfe, Stata |
CUDA | 22.7 | 161.7x |
xhdfe, Python |
CUDA | 14.5 | 252.2x |
The xhdfe rows use the speed-oriented xhdfe-fast mode; the default
reghdfe-comparable mode is somewhat slower but matches reghdfe more tightly.
- Multiway HDFE — any number of absorbed fixed-effect dimensions, plus two-way categorical interactions.
- Dual Python API — low-overhead arrays or an optional R-style formula frontend with categories and interactions.
- Publication tables — fitted Python results plug directly into
maketables.ETablewithout an adapter or runtime dependency. - Heterogeneous (group-specific) slopes —
fe#c.xandfe##c.xdesigns. - IV / 2SLS with absorbed fixed effects.
- Weights — analytic, frequency, probability, and importance weights.
- Robust and multiway-cluster standard errors.
- DoF adjustments — reghdfe-style singleton dropping and degrees-of-freedom logic, plus fixest-style small-sample corrections (
ssc). - Fixed-effect recovery —
savefe/savefes(Stata),fixef()(R),retain_fes(Python). - Group-level outcomes with individual fixed effects — the
group()/individual()machinery. - Mobility groups and connected-component diagnostics.
- Optional GPU — CUDA absorber with explicit request and status reporting; fail-closed (never a silent CPU fallback).
- AKM / worker-firm post-estimation — leave-out (KSS) variance decomposition with plug-in, AGSU and KSS corrections, exact and Johnson-Lindenstrauss leverages, component standard errors, Andrews-Mikusheva weak-identification confidence intervals, fweights, and a leave-one-out connected-set utility (
xhdfeakm/xhdfeconnectedin Stata,xhdfe.akmin Python,xhdfe_akm_kss()in R); validated against Saggio's LeaveOutTwoWay (the canonical KSS implementation) and pytwoway. Seedocs/akm-kss.md. - Gelbach decomposition —
xhdfegelbach/xhdfe.gelbach/xhdfe_gelbach(), validated against Gelbach'sb1x2on overlapping classic OLS specifications, with multiple focal coefficients, multiple observed blocks, common and added HDFEs, and explicitly declared absorbed targets. Version 1.6.0 includes retained-sample provenance, connectivity and regularity diagnostics, joint-covariance inference, full-refit pairs bootstrap, and table and plot helpers. Seedocs/releases/RELEASE_NOTES_2.23.0.20260806.md.
The three packages call the same C++ estimator, so results agree across languages. Pick your front-end below. For GPU (CUDA) acceleration in any of them, see the GPU (CUDA) guide — it walks through installing with the GPU feature, requesting it, and verifying it in Stata, Python, and R.
One command installs everything. net install xhdfe installs the estimator
and every companion command — xfe, xhdfeakm, xhdfeconnected,
xhdfegelbach, xhdfegelbachbootstrap, xhdfegelbachetable,
xhdfegelbachcoefplot, and xhdfegpu — together with the CPU plugin for your
OS:
net install xhdfe, from("https://raw.githubusercontent.com/reisportela/xhdfe-xfe/gh-pages/stata") replaceThat is all most users need. The commands you get:
| Command | What it does |
|---|---|
xhdfe |
HDFE linear regression — the estimator (help xhdfe). |
xfe |
Partials out / residualizes variables against the fixed effects, no regression (help xfe). |
xhdfeakm |
Worker-firm (AKM) leave-out (KSS) variance decomposition (help xhdfeakm). |
xhdfeconnected |
Largest leave-one-out connected set — KSS sample prep (help xhdfeconnected). |
xhdfegelbach |
Gelbach (2016) decomposition of coefficient movements (help xhdfegelbach). |
xhdfegelbachbootstrap |
Full-refit iid- or cluster-pairs bootstrap for Gelbach results (help xhdfegelbachbootstrap). |
xhdfegelbachetable |
Publication-oriented Gelbach tables (help xhdfegelbachetable). |
xhdfegelbachcoefplot |
Identity-preserving Gelbach waterfall plot (help xhdfegelbachcoefplot). |
xhdfegpu |
Builds and installs a CUDA GPU plugin for this machine (help xhdfegpu). |
If you want only the standalone xfe partial-out tool, you can install it by
itself with net install xfe, from("…") replace. The online package uses Stata
platform-specific g lines for Linux, macOS Apple Silicon/Intel, and Windows
when a Windows plugin artifact exists.
The online net-install site provides the CPU plugin. Certified releases may
also publish separate Linux CUDA plugin assets on the
Releases page. On a Linux
machine with an NVIDIA GPU, the most direct way to build for that machine is to
run the companion command once, right after net install:
xhdfegpuxhdfegpu detects the GPU, compiles a plugin for its exact architecture, and
installs it over the CPU plugin in place — same xhdfe.plugin / xfe.plugin,
no renaming, no extra files. Then reload the plugin and request the GPU as usual:
discard
xhdfe price weight length, absorb(rep78) gpubackend(cuda)
display e(gpu_used) // 1On a machine without internet access, download the self-contained source
zip (xhdfe-src.zip, attached to each release and served from the net-install
site) on another machine, copy it over, and hand it to xhdfegpu:
xhdfegpu, zip("/path/to/xhdfe-src.zip")xhdfegpu needs the NVIDIA CUDA toolkit (nvcc) and a C++ compiler; see
help xhdfegpu. The zip is self-contained: Eigen, pybind11, the official
version-pinned Rcpp source archive, and Stata's plugin inputs are vendored, so
the package-side build needs no further downloads.
Download the distribution ZIP from the
Releases page, unzip it,
and point net install at the folder that contains xhdfe.pkg and stata.toc
(this also installs xfe and the companions):
net install xhdfe, from("/path/to/unzipped/xhdfe/stata") replacexhdfegpu automates the GPU build; to do it yourself, get the source (clone the
repo, or download xhdfe-src.zip) and build, then add the folder to adopath:
git clone https://github.com/reisportela/xhdfe-xfe.git
cd xhdfe-xfe
# CPU build (Linux + GCC; OpenMP recommended)
bash stata/tools/build-plugin.sh --linux --openmp # produces stata/xhdfe.plugin
bash stata/tools/build-xfe-plugin.sh --linux --openmp # produces stata/xfe.plugin
# GPU build (Linux + NVIDIA; auto-detects the local architecture)
bash stata/tools/build-plugin.sh --linux --openmp --cuda auto
bash stata/tools/build-xfe-plugin.sh --linux --openmp --cuda autoFor an explicit target use --cuda 90; for a shareable multi-GPU binary,
--cuda-archs "75,80,86,89,90". See stata/BUILD_CUDA.md. Then
adopath + "/path/to/xhdfe/stata".
Minimal example (public data shipped with Stata):
sysuse auto, clear
xhdfe price weight length, absorb(rep78)
xhdfe price weight length, absorb(rep78) vce(cluster rep78)
webuse nlswork, clear
xhdfe ln_wage grade age ttl_exp tenure not_smsa south, absorb(idcode year)
xhdfe ln_wage grade age ttl_exp tenure not_smsa south, absorb(idcode year occ_code)
* GPU (after xhdfegpu, or a CUDA-enabled plugin): request CUDA and verify
xhdfe ln_wage grade age ttl_exp tenure, absorb(idcode year) gpubackend(cuda)
display e(gpu_used) // must be 1
display "`e(gpu_backend)'" // must be "cuda"Install from the repository. Python source builds require CMake, a C++ compiler,
and the Python development headers for the Python you are using (Python.h).
On Linux, install the matching system package first, for example
python3-dev on Debian/Ubuntu or python3-devel on Fedora/RHEL/Rocky. On
clusters without sudo, use a conda/mamba environment or a Python module that
includes development headers.
python -m pip install "git+https://github.com/reisportela/xhdfe-xfe.git"
# or, from a clone:
git clone https://github.com/reisportela/xhdfe-xfe.git && cd xhdfe-xfe && python -m pip install .With the GPU (CUDA) feature (Linux + NVIDIA only; needs the CUDA toolkit
nvcc and always builds from source — never a prebuilt wheel). Set
XHDFE_ENABLE_CUDA=auto: the build detects your GPU with nvidia-smi (the same
check Stata's xhdfegpu uses) and compiles for that exact architecture. If no
GPU or nvidia-smi is found it stops with a clear error — it never silently
builds CPU-only when you asked for CUDA (CPU stays the default, plain
pip install .).
# from a clone:
XHDFE_ENABLE_CUDA=auto python -m pip install .
# or straight from GitHub:
XHDFE_ENABLE_CUDA=auto python -m pip install "git+https://github.com/reisportela/xhdfe-xfe.git"For an explicit target, set XHDFE_CUDA_ARCH=90 or
CMAKE_CUDA_ARCHITECTURES=90.
At runtime request the GPU with os.environ["XHDFE_GPU_BACKEND"] = "cuda" (see
the example below) and confirm with reg.gpu_used_ == 1.
Minimal example:
import os
import numpy as np
import xhdfe
n = 2000
rng = np.random.default_rng(0)
y = rng.normal(size=n)
X = rng.normal(size=(n, 3))
firm_id = rng.integers(0, 200, size=n)
year_id = rng.integers(0, 20, size=n)
reg = xhdfe.HdfeRegressor(se_type="robust", tol=1e-8)
reg.fit(y, X, fes=[firm_id, year_id])
print(reg.coef_)
print(reg.summary())
# Optional: request CUDA after installing a CUDA-enabled build
os.environ["XHDFE_GPU_BACKEND"] = "cuda"
reg_gpu = xhdfe.HdfeRegressor(se_type="robust", tol=1e-8)
reg_gpu.fit(y, X, fes=[firm_id, year_id])
assert reg_gpu.gpu_used_ == 1
assert reg_gpu.gpu_status_code_ == 1
os.environ.pop("XHDFE_GPU_BACKEND", None)On Windows, a GNU/MinGW build recursively bundles every detected non-system DLL
dependency beside the extension. The package registers that internal directory
before loading the native module and retains the Windows DLL-directory handle,
so an installed wheel does not depend on the build toolchain remaining on
PATH and does not require a user-side os.add_dll_directory(...) call. The
build fails closed if the active toolchain cannot supply a matching x86-64
binary for any detected dependency. Machine-specific instruction tuning is
disabled by default on Windows, so source-built artefacts do not inherit the
build host's instruction set; explicitly local-only builds may opt in. The
prebuilt Windows asset in this release
is for CPython 3.12 x86-64; other Python ABIs require a source build and were
not separately Windows-certified for this release.
The optional R-style formula frontend uses the same native estimator while adding named dataframe designs. Install the extra from a source checkout:
python -m pip install '.[formula]'If xhdfe is already installed from a GitHub release asset, install its
optional formula dependency with
python -m pip install 'formulaic>=1.2.1,<2' 'pandas>=1.3'.
model = xhdfe.feols(
"y ~ x1 + x2 + C(industry) | firm + year",
data=d,
se_type="cluster",
clusters="firm",
)
print(model.tidy())C(g) is the R-style counterpart of Stata's i.g; x:z is a product-only
interaction and x*z expands to x + z + x:z. Fixed effects after | are
read as identifier columns, encoded as group IDs, and passed to the native
absorber, so they do not become dummy columns. A third part requests 2SLS with
the same spelling as the R frontend, its left side naming the endogenous
regressors and its right side the excluded instruments:
model = xhdfe.feols("y ~ x1 | firm + year | d ~ z1 + z2", data=d)The existing
HdfeRegressor.fit(y, X, ...) API remains the lowest-overhead route for small
regressions in loops. See the packaged Python help for formula semantics,
categorical reference levels, and prepare_formula().
Fitted results implement the duck-typed plug-in format of maketables, so publication tables need no adapter or registration step:
import maketables as mt
print(mt.ETable([model_a, model_b], drop="Intercept").make(type="tex"))maketables is not an xhdfe dependency. Absorbed fixed effects become indicator rows, singleton counts and absorbed degrees of freedom are available as table statistics, and Stata variable labels carried on the estimation frame are picked up automatically. See the packaged Python help for the full statistic list.
Install from GitHub (the package lives in the r/xhdfe subdirectory). This
gives you the CPU build:
# install.packages("remotes")
remotes::install_github("reisportela/xhdfe-xfe", subdir = "r/xhdfe")With the GPU (CUDA) feature (Linux + NVIDIA only; needs the CUDA toolkit
nvcc and always builds from source). Set XHDFE_ENABLE_CUDA=auto: the build
detects your GPU with nvidia-smi (the same check Stata's xhdfegpu uses) and
compiles for that exact architecture, failing with a clear error if no GPU or
nvidia-smi is found rather than silently building CPU-only (CPU is the default
install_github):
Sys.setenv(XHDFE_ENABLE_CUDA = "auto")
remotes::install_github("reisportela/xhdfe-xfe", subdir = "r/xhdfe")or, from a clone: XHDFE_ENABLE_CUDA=auto R CMD INSTALL r/xhdfe. For an
explicit target, set XHDFE_CUDA_ARCH=90.
GPU use is then per call via backend = "cuda" (fail-closed if unavailable);
xhdfe_info() reports the CUDA arch the package was built for.
For a network-disabled installation from xhdfe-src.zip or the autonomous
offline bundle, install the pinned Rcpp source into a local library first:
mkdir -p r/Rlib
R_PROFILE_USER=/dev/null R_ENVIRON_USER=/dev/null \
R_LIBS_USER="$PWD/r/Rlib" \
R CMD INSTALL --library="$PWD/r/Rlib" third_party/Rcpp_1.1.2.tar.gz
R_PROFILE_USER=/dev/null R_ENVIRON_USER=/dev/null \
R_LIBS_USER="$PWD/r/Rlib" XHDFE_ENABLE_CUDA=OFF \
R CMD INSTALL --library="$PWD/r/Rlib" r/xhdfeThe unmodified CRAN archive's URL, license, version, and SHA-256 are recorded
in third_party/RCPP_SOURCE_PROVENANCE.md.
Minimal example (a small simulated worker–firm panel):
library(xhdfe)
set.seed(2026)
n <- 600
d <- data.frame(
worker = sample(80, n, replace = TRUE),
firm = sample(30, n, replace = TRUE),
x1 = rnorm(n),
x2 = rnorm(n)
)
d$y <- 0.5 * d$x1 - 0.2 * d$x2 + 0.05 * d$worker + 0.03 * d$firm + rnorm(n)
# Two-way fixed effects (worker + firm), clustered by firm
m <- xhdfe(y ~ x1 + x2 | worker + firm, data = d, cluster = ~ firm)
summary(m)
# Optional: request CUDA after installing a CUDA-enabled build
m_gpu <- xhdfe(y ~ x1 + x2 | worker + firm, data = d,
cluster = ~ firm, backend = "cuda")
stopifnot(m_gpu$gpu_used == 1, m_gpu$gpu_status == "used")The R formula grammar is fixest-style: y ~ x | fe1 + fe2 for absorbed FEs,
fe[slope] / fe[[slope]] for heterogeneous slopes, f1^f2 for a combined
interaction FE, and | endo ~ inst for IV. See
r/README.md for the CUDA build and the platform note, and
?xhdfe for the full documentation.
Beyond general-purpose HDFE regression, xhdfe ships a worker-firm layer that
follows the Kline-Saggio-Sølvsten (2020) leave-out methodology (validated
against Saggio's LeaveOutTwoWay and pytwoway) and a Gelbach (2016)
decomposition — all on the same compiled backend, in Stata, Python and R.
Installation is the same as the core (they are part of the one package).
Stata:
* leave-one-out connected set, then the AKM/KSS variance decomposition
xhdfeconnected worker firm, generate(insample)
xhdfeakm y, worker(worker) firm(firm) ci // KSS SEs + Andrews-Mikusheva CIs
xhdfegelbach y, x1(educ) x2groups("skill = ability") fes(firm)Python:
import xhdfe.akm as akm, xhdfe.gelbach as gelbach
r = akm.akm_kss(y, worker, firm, compute_se=True, eigen_diagnostics=True)
print(r["kss"], r["component_se"], r["weak_id"])
g = gelbach.decompose(y, educ, x2_groups={"skill": ability}, fes={"firm": firm})R:
fit <- xhdfe_akm_kss(y, worker, firm, compute_se = TRUE, eigen_diagnostics = TRUE)
g <- xhdfe_gelbach(y, x1 = educ, x2_groups = list(skill = ability),
fes = list(firm = firm))Gelbach's standard mode accounts for the movement from one base linear model to one full model. The separate absorbed-target mode covers a declared X1 target that belongs to an added FE span: its full coefficient is imposed at zero and explicitly labelled, never treated as an estimated within-FE effect. Inference for that target must be clustered at the absorbing FE dimension.
Version 1.5.0 supports multiple focal coefficients, multiple observed blocks,
HDFEs common to both models, and any number of added FE dimensions. Its
joint-covariance inference includes denominator uncertainty and the
cross-covariance term in shares(base) in Stata and share = "base" in
Python/R; the earlier base_fixed convention remains available as descriptive
fixed-denominator scaling. Results expose retained-sample provenance,
mobility-connectivity checks for supported two-way designs, weak-denominator
and regularity diagnostics, observed-block full-model coefficients, and
truthful CUDA-use metadata.
The reporting layer can fully refit the model under iid- or cluster-pairs
bootstrap draws and produce tables, coefficient plots, and waterfall data.
Use xhdfegelbachbootstrap, xhdfegelbachetable, and
xhdfegelbachcoefplot in Stata; gelbach.bootstrap, gelbach.etable,
gelbach.waterfall_data, and gelbach.coefplot in Python; or the corresponding
xhdfe_gelbach_* functions in R.
Run help xhdfegelbach, python -m xhdfe gelbach, or
?xhdfe_gelbach for the complete estimands, covariance layout, warnings,
reporting helpers, examples, and deliberate limits. The decomposition is
specification accounting, not evidence of causal mediation.
The plug-in, AGSU (homoskedastic) and KSS (heteroskedasticity-robust leave-out)
decompositions report the variance of worker effects, of firm effects, their
covariance and correlation, and the shares of wage variance; with se/ci
they add component standard errors and Andrews-Mikusheva weak-identification
confidence intervals. Exact and Johnson-Lindenstrauss leverages, frequency
weights and an optional CUDA solver are supported. Runnable examples in all
three languages live in examples/; a felsdvsimul walkthrough is
in docs/akm-kss.md.
In Stata, xhdfeakm 1.7.2 reports a single affected-row count when many
non-stayer observations hit the unit-leverage guard. This is a bounded
diagnostic change; it does not alter KSS estimates, tolerances, or convergence
decisions.
| Path | Contents |
|---|---|
src/, include/, third_party/ |
The shared C++ core and vendored build inputs: Eigen and pybind11 sources plus the pinned official Rcpp source archive used by autonomous offline release media. |
python/, xhdfe/ |
Python package (import xhdfe; the HdfeRegressor class). |
r/ |
R package (r/xhdfe/), examples, and helper tools. |
stata/ |
Stata package: xhdfe.ado, xfe.ado, help files, plugin sources (src/), and build scripts (tools/). |
tests/ |
tests/stata/: Stata certification and smoke tests; tests/validation/: Python oracle and cross-frontend validators; tests/benchmarks/: public benchmark replication. |
docs/ |
Quickstart and overview. |
CMakeLists.txt, pyproject.toml, setup.py |
Build configuration for the C++ core and Python bindings. |
- Quickstart & overview:
docs/quickstart.md,docs/overview.md. - GPU (CUDA):
docs/gpu.md— install-with-GPU, request, and verify in Stata/Python/R. - AKM + leave-out (KSS) & Gelbach:
docs/akm-kss.md;help xhdfeakm,help xhdfeconnected,help xhdfegelbach,help xhdfegelbachbootstrap,help xhdfegelbachetable,help xhdfegelbachcoefplot,python -m xhdfe gelbach, and?xhdfe_gelbach. - Release workflow:
docs/release-workflow.md. - Release history and certification:
docs/releases/,docs/certification/. - Stata:
help xhdfe,help xfe. - R:
?xhdfe,?fixef.xhdfe,?predict.xhdfe; feature tour inr/examples/. - Python:
python -m xhdfeorxhdfe-helpat the shell, orxhdfe.help_text()inside Python.
Under the default reghdfe-comparable tolerance mode, xhdfe coefficients,
standard errors, and recovered fixed effects match reghdfe at the same nominal
tolerance (down to the conditioning of the problem). The three packages are
cross-checked against each other and against the wider ecosystem —
reghdfe (Stata),
fixest (R),
pyfixest (Python), and
FixedEffectModels.jl
(Julia). This software is released as a proof of concept: please validate
estimates for your own research design. See DISCLAIMER.md.
If you use xhdfe in academic work, please cite it (see
CITATION.cff):
Portela, Miguel, and Tiago Tavares. 2026. xhdfe: High-dimensional fixed effects regression via a C++ backend. Version 2.24.1. https://github.com/reisportela/xhdfe-xfe
MIT — see LICENSE. xhdfe bundles the Eigen 3.4.0 headers
(primarily MPL-2.0, with parts under BSD-3-Clause and Apache-2.0); see
NOTICE. Autonomous release media also carry the unmodified official
Rcpp 1.1.2 source archive under its upstream GPL (>= 2) license solely as the
R package's offline build dependency; see
third_party/RCPP_SOURCE_PROVENANCE.md.
- Miguel Portela — NIPE / Universidade do Minho and BPLIM / Banco de Portugal.
- Tiago Tavares — NIPE / Universidade do Minho.
Development note: xhdfe was built with AI-assisted tooling, but only the two
listed humans are authors; no software tool or AI system is credited as an
author or co-author.
xhdfe validates against and interoperates with prior HDFE software. Full
credit goes to reghdfe by Sergio
Correia (Stata), fixest by Laurent
Berge (R), pyfixest by
Alexander Fischer and collaborators (Python), and
FixedEffectModels.jl
by Matthieu Gomez and collaborators (Julia).
By design, xhdfe is first and foremost a high-performance replica of
reghdfe: it mirrors reghdfe's estimator, defaults, and reporting, and
reghdfe-comparable results are its reference. From the worker-firm (AKM)
literature and from pytwoway — Thibaut
Lamadon and Adam A. Oppenheimer's reference Python toolkit for two-way worker-firm
models (AKM and the leave-out, CRE and BLM estimators) — xhdfe adopts only
what adds value inside that reghdfe universe: the leave-out (KSS) bias-corrected
variance decomposition, the leave-out connected set, and the Gelbach
decomposition, implemented natively on the same C++ core. It does not attempt to
reproduce pytwoway.
xhdfe links to pytwoway in two concrete ways. First, validation: its
leave-out decomposition is checked at machine precision against pytwoway and
against LeaveOutTwoWay by
Raffaele Saggio, the canonical Kline-Saggio-Sølvsten (2020) implementation.
Second, interoperability: xhdfe exports the leave-out sample to the
pytwoway / bipartitepandas format, so a cleaned two-way sample moves between
the two tools. The combination is most useful in labour economics with large
linked employer-employee data: run the fast HDFE regression and the leave-out
variance decomposition (variance of worker and firm effects, their covariance,
and worker-firm sorting) inside a familiar reghdfe workflow with xhdfe, and
reach for pytwoway when you need its broader structural models (CRE, BLM) that
are deliberately outside xhdfe's scope. The Gelbach decomposition is validated
against b1x2 by Jonah Gelbach. Full credit to their authors.
We thank Paulo Guimaraes, Marta Silva, and Nelson Areal for discussions and
workshop collaboration around earlier versions of the project. We especially
thank Sergio Correia for feedback on benchmarking, tolerances, and
reghdfe-comparable validation. We also warmly thank Alexander Fischer for
sharing the latest updates on his and Kristof Schröder's novel graph-based
fixed-effects demeaning strategy — a modified LSMR solver with an
additive-Schwarz preconditioner built from the worker-firm bipartite graph (the
within project) — which has been
very helpful for our ongoing work on high-dimensional demeaning. All remaining
errors are ours.
High-dimensional fixed effects — the reghdfe universe xhdfe replicates:
- Cornelissen, T. 2008. The Stata command
felsdvregto fit a linear model with two high-dimensional fixed effects. Stata Journal 8(2): 170-189. - Guimaraes, P., and P. Portugal. 2010. A simple feasible procedure to fit models with high-dimensional fixed effects. Stata Journal 10(4): 628-649.
- Gaure, S. 2013. OLS with multiple high dimensional category variables. Computational Statistics & Data Analysis 66: 8-18.
- Correia, S. 2016.
reghdfe: Estimating linear models with multi-way fixed effects. Stata Conference, Stata Users Group. - Correia, S., P. Guimaraes, and T. Zylkin. 2020. Fast Poisson estimation with high-dimensional fixed effects. Stata Journal 20(1): 95-115.
Worker-firm (AKM) leave-out layer — what xhdfe borrows from the pytwoway
literature (see Acknowledgements):
- Abowd, J. M., F. Kramarz, and D. N. Margolis. 1999. High wage workers and high wage firms. Econometrica 67(2): 251-333. (AKM two-way model.)
- Andrews, M. J., L. Gill, T. Schank, and R. Upward. 2008. High wage workers and low wage firms: negative assortative matching or limited mobility bias? Journal of the Royal Statistical Society A 171(3): 673-697. (AGSU homoskedastic correction.)
- Kline, P., R. Saggio, and M. Sølvsten. 2020. Leave-out estimation of variance components. Econometrica 88(5): 1859-1898. (KSS leave-out heteroskedasticity-robust correction and inference.)
- Andrews, I., and A. Mikusheva. 2016. A geometric approach to nonlinear econometric models. Econometrica 84(3): 1249-1264. (Weak-identification q=1 confidence intervals used by KSS.)
- Gelbach, J. B. 2016. When do covariates matter? And which ones, and how much? Journal of Labor Economics 34(2): 509-543. (Conditional decomposition of coefficient movements.)
Contributions, bug reports, and validation cases are welcome — see
CONTRIBUTING.md.
The C++ core, Python bindings, and R package target Linux x86-64, Windows x86-64, and macOS Apple Silicon/Intel source builds with the local platform toolchain. CUDA GPU acceleration is optional on Linux with the NVIDIA toolkit. The online Stata net-install site provides CPU plugins. Certified releases may also provide separate Linux CUDA fatbin plugins alongside Linux CPU/OpenMP, Windows x86-64 CPU/OpenMP, and macOS universal assets. Machine-specific CUDA plugins can be built from source on Linux with the NVIDIA toolkit.