Skip to content

FE

FE estimates a one-way (entity) or two-way (entity + time) fixed effects ("within") panel regression. It shares the general API shape with OLS (data/y/x/options constructor, .fit()), but entity (and optionally time) is a required argument rather than an option, since a fixed effects model has no meaning without a panel structure. There is no intercept: the within transformation removes it structurally, so FEOptions has no include_intercept field and FEResults.param_names never includes "const".

One-way vs. two-way

Whether the model is one-way (entity only) or two-way (entity + time) is controlled entirely by FEOptions.time: None (default) gives one-way, any column name gives two-way. Two-way fixed effects require a balanced panel; an unbalanced panel with time set raises a ValidationError. One-way fixed effects support unbalanced panels without restriction.

FEResults.n_periods is the number of unique time periods for two-way effects and None for one-way.

Standard error types

FEOptions.cov_type defaults to "cluster" (clustered on entity) rather than "classical" — a deliberate departure from OLS's default, following the same convention as fixest: panel data almost always has within-entity serial correlation, and defaulting to a robust-but-not-clustered type would understate it. Supported values are "classical", "hc1", "hc2", "hc3", "cluster", and "dk" — "hc0" is not supported (neither linearmodels nor fixest offer it for panel/FE models).

"dk" is not the same Newey-West estimator as OLS's: it is a Driscoll-Kraay panel HAC estimator (fixest's vcov="DK", Stata's xtscc), which is robust to both cross-entity and within-entity correlation. FEOptions.dk_time is required with "dk": it names the column that defines the time periods. It is never taken from FEOptions.time, which only sets the two-way fixed effects, so the fixed effects and the HAC kernel may use different time granularities (for example quarterly fixed effects with yearly periods for the kernel). FEOptions.dk_bandwidth sets the kernel bandwidth explicitly; when omitted it is chosen automatically from the number of unique time periods. The bandwidth actually used is reported as FEResults.dk_bandwidth_used (None unless cov_type="dk").

The small-sample corrections and the degrees of freedom of the t and F tests follow fixest's ssc() defaults: "cluster" scales by G/(G-1) · (n-1)/(n-K) and uses G - 1 degrees of freedom (G = number of clusters), "dk" uses T/(T-1) with T = number of time periods in place of G and T - 1 degrees of freedom, and the other types use df_resid. These differ from linearmodels, which does not apply the G/(G-1) factor. See Inference conventions for the full table.

Panel R²

FEResults reports three separate R² values instead of OLS's single r_squared/adj_r_squared pair, since "the" R² is not well-defined once fixed effects are involved: r_squared_within (based on the within-transformed variables), r_squared_between (based on entity-mean variables), and r_squared_overall (based on the untransformed variables).

Recovering the fixed effects

The fixed effects themselves (α_i for entity, γ_t for time) are not part of the fit() result; call FEResults.fixed_effects() separately. One-way returns dict[str, float] keyed by entity id. Two-way returns dict[str, dict[str, float]] with top-level keys "entity" and "time" — the two-way case has a normalization choice (which effect absorbs the overall level), so its values do not always match fixest::fixef() numerically; see the method's docstring for the exact convention.

econometricsmodels.FE(data, y, x, entity, options=None)

Fixed effects (within) panel regression estimator.

Supports one-way (entity) and two-way (entity + time) fixed effects, selected via FEOptions.time (docs/spec/fe-spec.md section 1).

Parameters:

Name Type Description Default
data DataFrame

A polars DataFrame containing the dependent variable, independent variables, entity identifier, and (if specified) time/cluster/HAC time columns.

required
y str

Column name of the dependent variable.

required
x list[str]

List of column names of the independent variables. Must contain at least one column name.

required
entity str

Column name of the entity (individual/panel unit) identifier.

required
options FEOptions | None

Estimation options. Defaults to FEOptions() (cov_type="cluster" on entity, one-way, confidence_level=0.95) when omitted.

None

Examples:

>>> import polars as pl
>>> from econometricsmodels import FE
>>> df = pl.DataFrame(
...     {
...         "y": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
...         "x1": [2.0, 4.0, 1.0, 5.0, 3.0, 6.0],
...         "id": ["a", "a", "b", "b", "c", "c"],
...     }
... )
>>> result = FE(df, y="y", x=["x1"], entity="id").fit()
>>> result.params["x1"]

fit()

Estimate the FE model.

Returns:

Type Description
FEResults

The estimation results.

Raises:

Type Description
TypeError

An argument has the wrong type (for example x is a string instead of a list of column names). A builtin exception, not a ValidationError.

ValidationError

The input or options are invalid (x is empty, a column is missing, contains missing values or NaN/infinity, y/x/entity/time overlap, insufficient observations, confidence_level out of range, an unknown cov_type (or cov_type="hc0", unsupported for FE), an unbalanced panel with two-way effects, a singleton entity/time group, or an explanatory variable with zero variance after the within transformation, cov_type="dk" without dk_time (the Driscoll-Kraay time periods are never taken from time), cov_type="dk" with no more unique time periods than regressors: the Driscoll-Kraay covariance has rank at most T-1, so the slope F-test cannot be computed, or cov_type="dk" with 2 time periods / cov_type="cluster" with 2 clusters where every entity (or, with two-way effects, every time period) is observed exactly once in each: the covariance is then identically zero). A subclass of ValueError.

ComputationError

A problem was detected during computation (e.g. a singular within-transformed design matrix). A subclass of RuntimeError.

econometricsmodels.FEOptions

Estimation options for FE (fixed effects panel regression).

See docs/spec/panel-common.md for the rationale behind each field's meaning and default value.

cluster property

Column name to use as the cluster group key when cov_type="cluster". When None, the entity argument's column is used automatically. Specifying it with any other cov_type raises ValidationError.

confidence_level property

Confidence level for confidence intervals, in the range (0, 1). Defaults to 0.95 (a 95% confidence interval).

cov_type property

Standard error type: one of "classical", "hc1", "hc2", "hc3", "cluster", "dk". Case-insensitive. Unlike OLS/WLS/IV, "hc0" is not supported (neither linearmodels nor fixest offer it for panel/FE regressions).

dk_bandwidth property

Bandwidth for Driscoll-Kraay HAC when cov_type="dk". When None, computed automatically via floor(4*(t/100)^(2/9)) (t = number of unique time periods). Specifying it with any other cov_type raises ValidationError.

dk_time property

Column name that defines the time periods of the Driscoll-Kraay HAC, independent of time (time and dk_time serve different purposes; see the module docstring). Required when cov_type="dk", in one-way and two-way models alike: leaving it unset raises ValidationError, and time is not used instead. With two-way effects the HAC may use a different time granularity from the fixed effects. It may not be the same column as y or entity (ValidationError), but may be one of the regressors or the same column as time. Specifying it with any other cov_type raises ValidationError. The periods are ordered by the values of the column (see time).

time property

Column name of the time identifier. When set, requests two-way fixed effects (entity + time); when None (default), one-way (entity only). It only defines the fixed-effects structure: it is never used as the Driscoll-Kraay time periods (set dk_time for that). The periods are ordered by the values of the column: numerically for integers and floats, chronologically for Date and Datetime, in the order of the categories for Enum, and alphabetically for strings and Categorical.

econometricsmodels.FEResults(raw)

FE estimation results.

Array-valued properties (params, std_errors, etc.) are exposed as dictionaries keyed by coefficient name (for O(1) lookup of a single parameter). Use coef_table() for a row-oriented listing.

fixed_effects() (the fixed effects themselves) is provided as a separate method rather than a field on this class (docs/spec/fe-spec.md section 3.5).

Parameters:

Name Type Description Default
raw FEResult

The estimation result object returned by _lib.fit_fe (_lib.FEResult).

required
Note

Users normally do not construct this directly; it is returned by FE.fit().

aic property

Akaike Information Criterion (AIC).

bic property

Bayesian Information Criterion (BIC).

conf_int property

Coefficient name to confidence interval (lower, upper).

cov_type property

Standard error type actually used (normalized to lowercase).

dep_var_name property

Column name of the dependent variable.

df_model property

Model degrees of freedom (k, the number of slope coefficients).

df_resid property

Residual degrees of freedom (n - n_entities - k for one-way, n - n_entities - n_periods + 1 - k for two-way).

dk_bandwidth_used property

Driscoll-Kraay bandwidth actually used: the explicit dk_bandwidth if given, otherwise the value chosen automatically, floor(4 * (t / 100) ** (2 / 9)) where t is the number of unique time periods in FEOptions.dk_time. None unless cov_type="dk".

f_df_denom property

Denominator degrees of freedom of f_statistic (None when it is NaN). Follows cov_type like the t-tests (G - 1 for cov_type="cluster", T - 1 for "dk", df_resid otherwise), so it equals stat_df whenever f_statistic is not NaN. Use this to recompute the p-value from f_statistic.

f_df_num property

Numerator degrees of freedom of f_statistic (None when it is NaN, i.e. there are no slope coefficients).

f_p_value property

P-value of the F-statistic.

f_statistic property

F-statistic for the joint significance of the slope coefficients (classical F-test when cov_type="classical", a robust Wald test otherwise).

log_likelihood property

Log-likelihood.

n_entities property

Number of panel entities.

n_obs property

Number of observations.

n_periods property

Number of unique time periods (two-way effects only; None for one-way). Two-way requires a balanced panel, so this equals the number of observations per entity.

p_values property

Coefficient name to two-sided p-value.

param_names property

List of coefficient names (no intercept: within-transformed variables have no constant term).

params property

Coefficient name to coefficient value.

r_squared_between property

Between R² (based on entity-mean variables).

r_squared_overall property

Overall R² (based on the untransformed variables).

r_squared_within property

Within R² (based on the within-transformed variables).

residuals property

Within-transformed residuals (in observation order).

stat_df property

Degrees of freedom of the t distribution behind test_stats, or None when stat_dist is "normal". May differ from df_resid (cluster-robust inference uses G - 1, Driscoll-Kraay T - 1), so use this to recompute p-values from test_stats.

stat_dist property

Distribution of test_stats: "t" (t-statistics) or "normal" (z-statistics).

std_errors property

Coefficient name to standard error.

test_stats property

Coefficient name to test statistic (t-statistic; see stat_dist).

coef_table()

Row-oriented summary table of the coefficients.

Shaped to be usable almost as-is in a REST API response (same policy as OLSResults.coef_table()). Returned as list[dict] rather than a polars DataFrame, per the project's policy of not using DataFrames for the coefficient table itself.

Returns:

Type Description
list[dict[str, float | str]]

A list of dictionaries, one per coefficient. Keys are

list[dict[str, float | str]]

param, coef, std_err, test_stat, p_value,

list[dict[str, float | str]]

conf_lower, conf_upper.

fixed_effects()

The fixed effects themselves (α_i for entity, γ_t for time), recovered post-hoc from the fitted coefficients.

One-way: dict[str, float] keyed by entity id. Two-way: dict[str, dict[str, float]] with top-level keys "entity"/ "time". See docs/spec/fe-spec.md section 3.5 and _lib.FEResult.fixed_effects's docstring for the exact formula, including the two-way normalization convention. α_i/γ_t are not individually identified in the two-way case, so γ_t of the first period in time order (the order of the values of the time column) is fixed to 0 and α_i absorbs the overall level. The "time" dictionary lists the periods in time order. fixest::fixef() instead uses the first time value in observation order as the reference, so the two match numerically only when both choose the same reference period.

Returns:

Type Description
dict[str, float] | dict[str, dict[str, float]]

The fixed effects, shaped as described above.