Skip to content

Commit 32bbf90

Browse files
committed
initial commit
1 parent 4c59151 commit 32bbf90

File tree

7 files changed

+702
-32
lines changed

7 files changed

+702
-32
lines changed

pyfixest/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# Import frequently used functions and classes
1212
from pyfixest.estimation import (
1313
bonferroni,
14+
feglm,
1415
feols,
1516
fepois,
1617
rwolf,
@@ -33,6 +34,7 @@
3334
"estimation",
3435
"etable",
3536
"event_study",
37+
"feglm",
3638
"feols",
3739
"fepois",
3840
"get_data",

pyfixest/estimation/FixestMulti_.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import pandas as pd
66

7+
from pyfixest.estimation.feglm import Felogit
78
from pyfixest.estimation.feiv_ import Feiv
89
from pyfixest.estimation.feols_ import Feols, _check_vcov_input, _deparse_vcov_input
910
from pyfixest.estimation.feols_compressed_ import FeolsCompressed
@@ -334,6 +335,33 @@ def _estimate_all_models(
334335
FIT.to_array()
335336
FIT.drop_multicol_vars()
336337

338+
elif _method == "feglm-logit":
339+
FIT = Felogit(
340+
FixestFormula=FixestFormula,
341+
data=_data,
342+
ssc_dict=_ssc_dict,
343+
drop_singletons=_drop_singletons,
344+
drop_intercept=_drop_intercept,
345+
weights=_weights,
346+
weights_type=_weights_type,
347+
solver=solver,
348+
collin_tol=collin_tol,
349+
fixef_tol=_fixef_tol,
350+
lookup_demeaned_data=lookup_demeaned_data,
351+
tol=iwls_tol,
352+
maxiter=iwls_maxiter,
353+
store_data=_store_data,
354+
copy_data=_copy_data,
355+
lean=_lean,
356+
sample_split_value=sample_split_value,
357+
sample_split_var=_splitvar,
358+
separation_check=separation_check,
359+
)
360+
361+
FIT.prepare_model_matrix()
362+
FIT.to_array()
363+
FIT.drop_multicol_vars()
364+
337365
elif _method == "compression":
338366
FIT = FeolsCompressed(
339367
FixestFormula=FixestFormula,

pyfixest/estimation/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
detect_singletons,
77
)
88
from pyfixest.estimation.estimation import (
9+
feglm,
910
feols,
1011
fepois,
1112
)
13+
from pyfixest.estimation.feglm import Felogit
1214
from pyfixest.estimation.feiv_ import (
1315
Feiv,
1416
)

pyfixest/estimation/estimation.py

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,223 @@ def fepois(
650650
return fixest.fetch_model(0, print_fml=False)
651651

652652

653+
def feglm(
654+
fml: str,
655+
data: DataFrameType, # type: ignore
656+
family: str,
657+
vcov: Optional[Union[VcovTypeOptions, dict[str, str]]] = None,
658+
ssc: Optional[dict[str, Union[str, bool]]] = None,
659+
fixef_rm: FixedRmOptions = "none",
660+
fixef_tol: float = 1e-08,
661+
iwls_tol: float = 1e-08,
662+
iwls_maxiter: int = 25,
663+
collin_tol: float = 1e-10,
664+
separation_check: Optional[list[str]] = None,
665+
solver: SolverOptions = "np.linalg.solve",
666+
drop_intercept: bool = False,
667+
i_ref1=None,
668+
copy_data: bool = True,
669+
store_data: bool = True,
670+
lean: bool = False,
671+
split: Optional[str] = None,
672+
fsplit: Optional[str] = None,
673+
) -> Union[Feols, Fepois, FixestMulti]:
674+
"""
675+
Estimate GLM regression model with fixed effects.
676+
677+
Parameters
678+
----------
679+
fml : str
680+
A two-sided formula string using fixest formula syntax.
681+
Syntax: "Y ~ X1 + X2 | FE1 + FE2". "|" separates left-hand side and fixed
682+
effects.
683+
Special syntax includes:
684+
- Stepwise regressions (sw, sw0)
685+
- Cumulative stepwise regression (csw, csw0)
686+
- Multiple dependent variables (Y1 + Y2 ~ X)
687+
- Interaction of variables (i(X1,X2))
688+
- Interacted fixed effects (fe1^fe2)
689+
Compatible with formula parsing via the formulaic module.
690+
691+
data : DataFrameType
692+
A pandas or polars dataframe containing the variables in the formula.
693+
694+
family : str
695+
The family of the GLM model. Options include "logit".
696+
697+
vcov : Union[VcovTypeOptions, dict[str, str]]
698+
Type of variance-covariance matrix for inference. Options include "iid",
699+
"hetero", "HC1", "HC2", "HC3", or a dictionary for CRV1/CRV3 inference.
700+
701+
ssc : str
702+
A ssc object specifying the small sample correction for inference.
703+
704+
fixef_rm : FixedRmOptions
705+
Specifies whether to drop singleton fixed effects.
706+
Options: "none" (default), "singleton".
707+
708+
fixef_tol: float, optional
709+
Tolerance for the fixed effects demeaning algorithm. Defaults to 1e-08.
710+
711+
iwls_tol : Optional[float], optional
712+
Tolerance for IWLS convergence, by default 1e-08.
713+
714+
iwls_maxiter : Optional[float], optional
715+
Maximum number of iterations for IWLS convergence, by default 25.
716+
717+
collin_tol : float, optional
718+
Tolerance for collinearity check, by default 1e-10.
719+
720+
separation_check: list[str], optional
721+
Methods to identify and drop separated observations.
722+
Either "fe" or "ir". Executes "fe" by default (when None).
723+
724+
solver : SolverOptions, optional.
725+
The solver to use for the regression. Can be either "np.linalg.solve" or
726+
"np.linalg.lstsq". Defaults to "np.linalg.solve".
727+
728+
drop_intercept : bool, optional
729+
Whether to drop the intercept from the model, by default False.
730+
731+
i_ref1: None
732+
Deprecated with pyfixest version 0.18.0. Please use i-syntax instead, i.e.
733+
fepois('Y~ i(f1, ref=1)', data = data) instead of the former
734+
fepois('Y~ i(f1)', data = data, i_ref=1).
735+
736+
copy_data : bool, optional
737+
Whether to copy the data before estimation, by default True.
738+
If set to False, the data is not copied, which can save memory but
739+
may lead to unintended changes in the input data outside of `fepois`.
740+
For example, the input data set is re-index within the function.
741+
As far as I know, the only other relevant case is
742+
when using interacted fixed effects, in which case you'll find
743+
a column with interacted fixed effects in the data set.
744+
745+
store_data : bool, optional
746+
Whether to store the data in the model object, by default True.
747+
If set to False, the data is not stored in the model object, which can
748+
improve performance and save memory. However, it will no longer be possible
749+
to access the data via the `data` attribute of the model object. This has
750+
impact on post-estimation capabilities that rely on the data, e.g. `predict()`
751+
or `vcov()`.
752+
753+
lean: bool, optional
754+
False by default. If True, then all large objects are removed from the
755+
returned result: this will save memory but will block the possibility
756+
to use many methods. It is recommended to use the argument vcov
757+
to obtain the appropriate standard-errors at estimation time,
758+
since obtaining different SEs won't be possible afterwards.
759+
760+
split: Optional[str]
761+
A character string, i.e. 'split = var'. If provided, the sample is split according to the
762+
variable and one estimation is performed for each value of that variable. If you also want
763+
to include the estimation for the full sample, use the argument fsplit instead.
764+
765+
fsplit: Optional[str]
766+
This argument is the same as split but also includes the full sample as the first estimation.
767+
768+
Returns
769+
-------
770+
object
771+
An instance of the `Fepois` class or an instance of class `FixestMulti`
772+
for multiple models specified via `fml`.
773+
774+
Examples
775+
--------
776+
The `fepois()` function can be used to estimate a simple Poisson regression
777+
model with fixed effects.
778+
The following example regresses `Y` on `X1` and `X2` with fixed effects for
779+
`f1` and `f2`: fixed effects are specified after the `|` symbol.
780+
781+
```{python}
782+
import pyfixest as pf
783+
784+
data = pf.get_data(model = "Fepois")
785+
fit = pf.fepois("Y ~ X1 + X2 | f1 + f2", data)
786+
fit.summary()
787+
```
788+
For more examples, please take a look at the documentation of the `feols()`
789+
function.
790+
"""
791+
if family != "logit":
792+
raise ValueError("Only the family 'logit' is supported.")
793+
794+
if separation_check is None:
795+
separation_check = ["fe"]
796+
if ssc is None:
797+
ssc = ssc_func()
798+
if i_ref1 is not None:
799+
raise FeatureDeprecationError(
800+
"""
801+
The 'i_ref1' function argument is deprecated with pyfixest version 0.18.0.
802+
Please use i-syntax instead, i.e. fepois('Y~ i(f1, ref=1)', data = data)
803+
instead of the former fepois('Y~ i(f1)', data = data, i_ref=1).
804+
"""
805+
)
806+
807+
# WLS currently not supported for GLM regression
808+
weights = None
809+
weights_type = "aweights"
810+
811+
_estimation_input_checks(
812+
fml=fml,
813+
data=data,
814+
vcov=vcov,
815+
weights=weights,
816+
ssc=ssc,
817+
fixef_rm=fixef_rm,
818+
collin_tol=collin_tol,
819+
copy_data=copy_data,
820+
store_data=store_data,
821+
lean=lean,
822+
fixef_tol=fixef_tol,
823+
weights_type=weights_type,
824+
use_compression=False,
825+
reps=None,
826+
seed=None,
827+
split=split,
828+
fsplit=fsplit,
829+
separation_check=separation_check,
830+
)
831+
832+
fixest = FixestMulti(
833+
data=data,
834+
copy_data=copy_data,
835+
store_data=store_data,
836+
lean=lean,
837+
fixef_tol=fixef_tol,
838+
weights_type=weights_type,
839+
use_compression=False,
840+
reps=None,
841+
seed=None,
842+
split=split,
843+
fsplit=fsplit,
844+
)
845+
846+
# same checks as for Poisson regression
847+
fixest._prepare_estimation(
848+
f"feglm-{family}", fml, vcov, weights, ssc, fixef_rm, drop_intercept
849+
)
850+
if fixest._is_iv:
851+
raise NotImplementedError(
852+
"IV Estimation is not supported for Poisson Regression"
853+
)
854+
855+
fixest._estimate_all_models(
856+
vcov=vcov,
857+
iwls_tol=iwls_tol,
858+
iwls_maxiter=iwls_maxiter,
859+
collin_tol=collin_tol,
860+
separation_check=separation_check,
861+
solver=solver,
862+
)
863+
864+
if fixest._is_multiple_estimation:
865+
return fixest
866+
else:
867+
return fixest.fetch_model(0, print_fml=False)
868+
869+
653870
def _estimation_input_checks(
654871
fml: str,
655872
data: DataFrameType,

0 commit comments

Comments
 (0)