statspai.fixest¶
fixest ¶
High-dimensional fixed effects estimation via pyfixest.
This module provides thin wrappers around pyfixest's estimation functions,
converting results into StatsPAI's EconometricResults for seamless
integration with outreg2 and the rest of the ecosystem.
Requires: pip install pyfixest
Examples:
>>> import os
>>> import tempfile
>>> import numpy as np
>>> import pandas as pd
>>> from statspai.fixest import feols, fepois
>>> rng = np.random.default_rng(0)
>>> n = 300
>>> df = pd.DataFrame({'firm': rng.integers(0, 20, n),
... 'year': rng.integers(2000, 2006, n),
... 'experience': rng.normal(10, 3, n),
... 'rd_spending': rng.normal(5, 1, n)})
>>> df['wage'] = 1 + 0.5 * df['experience'] + rng.normal(size=n)
>>> df['patents'] = rng.poisson(np.exp(0.2 * df['rd_spending'] - 0.5))
>>>
>>> # Two-way fixed effects with clustered SEs
>>> # (pyfixest's first call JIT-compiles for ~20 s, hence the skips)
>>> result = feols("wage ~ experience | firm + year",
... data=df, vcov={"CRV1": "firm"})
>>> report = result.summary()
>>>
>>> # Poisson regression
>>> result = fepois("patents ~ rd_spending | firm", data=df)
>>>
>>> # Works with outreg2
>>> from statspai import outreg2
>>> path = os.path.join(tempfile.mkdtemp(), "table.xlsx")
>>> outreg2(result, filename=path)
Regression results exported to: ...table.xlsx
etable ¶
etable(*results: EconometricResults, **kwargs: Any) -> Any
Display a pyfixest-style regression table for StatsPAI results.
If every result carries a _pyfixest_fit reference, uses pyfixest's
native etable. Otherwise returns one row per term with
"coef*** (se)" cells, formatted by :func:sp.regtable so both tables
report identical numbers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*results
|
EconometricResults
|
One or more fitted results. |
()
|
**kwargs
|
Any
|
Passed to |
{}
|
Returns:
| Type | Description |
|---|---|
str or DataFrame
|
|
Examples:
Side-by-side comparison of nested specifications:
>>> import numpy as np
>>> import pandas as pd
>>> import statspai as sp
>>> rng = np.random.default_rng(1)
>>> n = 200
>>> df = pd.DataFrame({"x1": rng.normal(size=n), "x2": rng.normal(size=n),
... "firm": rng.integers(0, 10, n)})
>>> df["wage"] = 1.0 + 0.5 * df["x1"] - 0.3 * df["x2"] + rng.normal(0, 0.5, n)
>>> r1 = sp.regress("wage ~ x1", data=df)
>>> r2 = sp.regress("wage ~ x1 + x2", data=df)
>>> tab = sp.etable(r1, r2) # DataFrame: one coefficient column per model
>>> list(tab.columns)
['(1)', '(2)']
With sp.feols fits (requires the fixest extra), pyfixest's
native styled table is returned instead:
>>> f1 = sp.feols("wage ~ x1 | firm", data=df)
>>> f2 = sp.feols("wage ~ x1 + x2 | firm", data=df)
>>> tab = sp.etable(f1, f2)
A list works too: sp.etable([r1, r2]).
feglm ¶
feglm(fml: str, data: DataFrame, family: str = 'gaussian', vcov: Optional[Union[str, Dict[str, str]]] = None, *, cluster: Optional[str] = None, wild_reps: int = 9999, wild_weight_type: str = 'rademacher', seed: Optional[int] = None, conley_lat: Optional[str] = None, conley_lon: Optional[str] = None, conley_cutoff: Optional[float] = None, backend: str = 'auto', bias_correction: bool = False, **kwargs: Any) -> Union[EconometricResults, List[EconometricResults]]
Estimate GLM (logit, probit, negative binomial, Gaussian) with high-dimensional fixed effects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fml
|
str
|
pyfixest formula. |
required |
data
|
DataFrame
|
Input dataset. |
required |
family
|
str
|
GLM family: |
"gaussian"
|
vcov
|
str or dict
|
Variance-covariance estimator ( |
None
|
cluster
|
str
|
Cluster id column for the extended |
None
|
wild_reps
|
int
|
Replications for |
9999
|
wild_weight_type
|
str
|
Wild weight distribution ( |
"rademacher"
|
seed
|
int
|
RNG seed for sampled (non-enumerated) |
None
|
backend
|
(auto, pyfixest, native)
|
|
'auto'
|
bias_correction
|
bool
|
With |
False
|
**kwargs
|
Any
|
Additional arguments passed to |
{}
|
Returns:
| Type | Description |
|---|---|
EconometricResults or list of EconometricResults
|
|
Examples:
Logit GLM with firm fixed effects:
>>> import statspai as sp
>>> import numpy as np
>>> import pandas as pd
>>> rng = np.random.default_rng(0)
>>> n = 500
>>> firm = rng.integers(0, 8, n)
>>> x1 = rng.normal(size=n)
>>> p = 1.0 / (1.0 + np.exp(-(0.2 + 0.8 * x1)))
>>> y = (rng.random(n) < p).astype(int)
>>> df = pd.DataFrame({"y": y, "x1": x1, "firm": firm})
>>> res = sp.feglm("y ~ x1 | firm", data=df, family="logit")
>>> "x1" in res.params.index
True
feols ¶
feols(fml: str, data: DataFrame, vcov: Optional[Union[str, Dict[str, str]]] = None, *, weights: Optional[str] = None, ssc: Optional[Any] = None, fixef_rm: Optional[str] = 'singleton', collin_tol: float = 1e-06, lean: bool = False, cluster: Optional[str] = None, wild_reps: int = 999, wild_weight_type: str = 'rademacher', seed: Optional[int] = None, conley_lat: Optional[str] = None, conley_lon: Optional[str] = None, conley_cutoff: Optional[float] = None, backend: str = 'auto', weights_as: Optional[str] = None, **kwargs: Any) -> Union[EconometricResults, List[EconometricResults]]
Estimate OLS / IV with high-dimensional fixed effects.
Uses the Frisch-Waugh-Lovell theorem for fast absorption of high-dimensional fixed effects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fml
|
str
|
A pyfixest-style formula. Examples:
|
required |
data
|
DataFrame
|
Input dataset. |
required |
vcov
|
str or dict
|
Variance-covariance estimator (
|
None
|
weights
|
str
|
Column name for regression weights. Alone they are analytic
weights (Stata |
None
|
weights_as
|
(analytic, sampling)
|
What the weights are. |
'analytic'
|
ssc
|
optional
|
Small-sample correction via |
None
|
fixef_rm
|
(singleton, none)
|
Singleton fixed-effect groups: .. versionchanged:: 1.40.0
The default was |
'singleton'
|
collin_tol
|
float
|
Collinearity tolerance. |
1e-6
|
lean
|
bool
|
If True, drop large intermediate arrays to save memory. |
False
|
cluster
|
str
|
Cluster id column for the extended |
None
|
wild_reps
|
int
|
Bootstrap replications for |
999
|
wild_weight_type
|
str
|
Wild weight distribution ( |
"rademacher"
|
seed
|
int
|
RNG seed for |
None
|
conley_lat
|
str
|
Coordinate columns (decimal degrees) for |
None
|
conley_lon
|
str
|
Coordinate columns (decimal degrees) for |
None
|
conley_cutoff
|
float
|
Conley distance cutoff in km for |
None
|
backend
|
(auto, pyfixest, native)
|
|
'auto'
|
**kwargs
|
Any
|
Additional arguments passed to |
{}
|
Returns:
| Type | Description |
|---|---|
EconometricResults or list of EconometricResults
|
Single result for simple formulas, list for multiple estimations
(e.g. |
Examples:
Two-way fixed effects with clustered SEs:
>>> import statspai as sp
>>> import numpy as np
>>> import pandas as pd
>>> rng = np.random.default_rng(0)
>>> n = 400
>>> firm = rng.integers(0, 8, n)
>>> year = rng.integers(0, 5, n)
>>> x1 = rng.normal(size=n)
>>> y = 1.0 + 0.5 * x1 + 0.1 * firm + 0.2 * year + rng.normal(0, 0.5, n)
>>> df = pd.DataFrame({"y": y, "x1": x1, "firm": firm, "year": year})
>>> res = sp.feols("y ~ x1 | firm + year", data=df, vcov={"CRV1": "firm"})
>>> "x1" in res.params.index
True
Multiple estimation (csw0 returns a list, one fit per FE set):
>>> results = sp.feols("y ~ x1 | csw0(firm, year)", data=df)
>>> summaries = [r.summary() for r in results]
Use with outreg2 to build a regression table:
fepois ¶
fepois(fml: str, data: DataFrame, vcov: Optional[Union[str, Dict[str, str]]] = None, *, weights: Optional[str] = None, ssc: Optional[Any] = None, fixef_rm: Optional[str] = 'singleton', collin_tol: float = 1e-06, iwls_tol: float = 1e-08, iwls_maxiter: int = 25, cluster: Optional[str] = None, wild_reps: int = 9999, wild_weight_type: str = 'rademacher', seed: Optional[int] = None, conley_lat: Optional[str] = None, conley_lon: Optional[str] = None, conley_cutoff: Optional[float] = None, backend: str = 'auto', **kwargs: Any) -> Union[EconometricResults, List[EconometricResults]]
Estimate Poisson regression with high-dimensional fixed effects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fml
|
str
|
pyfixest formula. E.g. |
required |
data
|
DataFrame
|
Input dataset. |
required |
vcov
|
str or dict
|
Variance-covariance estimator (
|
None
|
weights
|
str
|
Column name for regression weights (not supported with the extended
|
None
|
ssc
|
optional
|
Small-sample correction. |
None
|
fixef_rm
|
(singleton, none)
|
Singleton fixed-effect groups: .. versionchanged:: 1.40.0
The default was |
'singleton'
|
collin_tol
|
float
|
Collinearity tolerance. |
1e-6
|
iwls_tol
|
float
|
IWLS convergence tolerance. |
1e-8
|
iwls_maxiter
|
int
|
Max IWLS iterations. |
25
|
cluster
|
str
|
Cluster id column for the extended |
None
|
wild_reps
|
int
|
Replications for |
9999
|
wild_weight_type
|
str
|
Wild weight distribution ( |
"rademacher"
|
seed
|
int
|
RNG seed for sampled (non-enumerated) |
None
|
backend
|
(auto, pyfixest, native)
|
|
'auto'
|
**kwargs
|
Any
|
Additional arguments passed to |
{}
|
Returns:
| Type | Description |
|---|---|
EconometricResults or list of EconometricResults
|
|
Examples:
Poisson regression (PPML-style) with firm fixed effects:
>>> import statspai as sp
>>> import numpy as np
>>> import pandas as pd
>>> rng = np.random.default_rng(0)
>>> n = 400
>>> firm = rng.integers(0, 8, n)
>>> x1 = rng.normal(size=n)
>>> mu = np.exp(0.3 + 0.5 * x1 + 0.1 * firm)
>>> df = pd.DataFrame({"y": rng.poisson(mu), "x1": x1, "firm": firm})
>>> res = sp.fepois("y ~ x1 | firm", data=df)
>>> "x1" in res.params.index
True
Bias-reduced cluster-robust SEs (matches R clubSandwich::vcovCR):