Releases: py-econometrics/pyfixest
PyFixest 0.50.0
Highlights:
- A new and fast demeaner backend!
- Much improved formula parsing.
- GLMs with fixed effects!
For the full changelog, see here: https://pyfixest.org/changelog.html
Pre-Release: PyFixest 0.50.0-a2
This release adds support for the CG-Schwarz demeaner backend via demeaner_backend = "rust-cg".
import pyfixest as pf
data = pf.get_data()
pf.feols("Y ~ X1 | f1 + f2", data=data, demean_backend="rust-cg")Pre-release for pyfixest 0.50:
Pre-release for pyfixest 0.50:
Highlights:
- We fully reworked formula parser and new i-operator capabilities
- We add fixed effect support for GLMs
- We spun out all work of
pf.etableto maketables
For more details, see the changelog: link
We aim for a full release for the second week of March. Until then, we very much appreciate your feedback!
PyFixest 0.40.1
Patch release to also install runtime dependencies from PyPi.
PyFixest 0.40.0
This release comes with a range of breaking changes and new features.
Breaking Changes
Compatibility with fixest 0.13
fixest 0.13 has recently been released to CRAN, with a range of breaking changes. We are following these in pyfixet 0.40.0.
- The default inference method is now always "iid". Before, both
fixestandpyfixestwould default to cluster by the first fixest effect
in the presence of fixed effect. - The arguments of the
pf.ssc()functions have been renamed:adjbecomesk_adj,fixef_kbecomesk_fixef,cluster_dfbecomesG_df, andcluster_adjbecomesG_adj.
Backwards compatibility is ensured. fixestno longer applies theG/(G-1)small sample correction for heteroskedastic errors. The argument is now only relevant for cluster robust errors.- If the
k_adjarg is set toTruewith heteroskedastic errors, the applied small sample correction now isN / (N-k)and no longer(N-1) / (N-df_k),
as was previously the case and is still the case for iid and cluster robust errors. - The
k_fixefoption"nested"has been renamed to"nonnested". - The
fixef_rmargument is changed from default"none"to"singleton"for all estimation functions. This has no impact on point estimates, but might change inference due to a smaller number of
observations in the degree of freedom correction. - The multicollinearity default tolerance has been reduced from 1e-10 to 1e-09.
- The attribute
_dof_khas been renamed to_df_k.
Other related changes:
- The arguments to adjust the small samples for the
wildboottestmethods have been renamed tok_adjandG_adj.
Updates to Gelbach Decomposition
We have reworked the Gelbach Decomposition method, with some breaking changes: by default, calling Feols.decompose() now returns a GelbachDecomposition instance - before, we'd return a pd.DataFrame. The param argument has been renamed to decomp_var, but is not yet deprecated.
The class now comes with new tidy() and etable() methods.
from pyfixest.utils.dgps import gelbach_data
import numpy as np
import pyfixest as pf
# Generate test data using gelbach_data
data = gelbach_data(nobs=500)
data["w"] = np.random.rand(500)
fit = pf.feols("y ~ x1 + x21 + x22 + x23", data=data)
gb = fit.decompose(decomp_var = "x1", x1_vars = ["x21"],reps = 10, nthreads = 1)
print(type(gb))
It is now also possible to add background variables that are included in both the long and short regressions via the x1_vars function argument.
We can inspect results as a pd.DataFrame
gb.tidy()
or produce a GT table:
gb.etable(
stats = "all",
caption = "Gelbach Decomposition"
)
As can be seen, we by default now return normalized (and not just absolute) effects.
We are now also supporting frequency weights for the decomposition (currently without inference).
Additionally, some house keeping and interal refactoring of the GelbachDecomposition class.
Moved to pixi.toml and install from conda-forge
We have been using pixi as our package manager for a while and are moving from a pyproject.toml to using a pixi.toml for specifying dependencies.
We also install all package by default from the free and open source conda-forge. Because of some environment resolution challenges around an old version of
rpy2that we need for testing pyfixest against fixest, we temporarily have dropped support for the dev and docs environments for windows. A fix is
work in progress.
New Features
CuPy and SciPy Backends via LSMR
We add CuPy and SciPy Backend to run the demeaning algorithm on the GPU via the sparse LSMR solver. For problems
where the standard demeaner struggles to converge, this strategy can lead to significant speedups if paired with a GPU.
HAC Standard Errors
We now support HAC standard errors! Thanks for Daman (@damandhaliwal) for all his work (and coping with me with the PR, which took forever to get through).
We now support:
- time series HAC
- panel HAC
- panel DK
variance-covariance matrices.
For now, we assume that the time series column is consecutive and each entry has "time delta 1". Relaxation of this requirement are work in progress.
cat_template argument for plotting functions
For easier encoding of categorical variables in relation to the iplot() and coefplot() functions, we add a new function argument, cat_template:
fit_c = pf.feols(fml = "Y ~ i(X1, f1)", data = df)
fit_c.iplot(cat_template = "{variable}::{value}")
This is particularly useful for Difference-in-Differences and event studies. You can find an example use case in the DiD vignette.
Going forward, we will deprecate the rename_event_study_coefs function, which is no longer needed (and did not work anyways).
v0.30.2a Release to re-trigger PyPi upload
Dummy release to trigger PyPi upload.
v0.30.2 - Fix Type Error on Windows
Windows user may experience a type error when using the Rust backend with 0.30.1. Here we try to address this error.
Hotfix Release for JAX import error
The previous release lead to a JAX import error. This release fixes the error.
v0.30.1
Release v0.30.1
v0.30.0
What's Changed
New Features
We have created a Rust backend for all performance critical algorithms, with pretty great performance improvements! You can use the Rust backend by setting demeaner_options = "rust".
We find pretty great performance improvements and want to make the Rust backend the default in PyFixest 0.31.0.
We now support quantile regression, including a Frisch-Newton Interior Point Solver with and without preprocessing, iid, heteroskedastic and cluster robust standard errors, fast algorithms for the entire quantile regression process, and some visualisations. In particular the algorithms for the quantile regression process show excellent performance. You can
learn more about all features and take a look at more systematic benchmarks in the quantreg vignette.
N_qr = 10_000
rng = np.random.default_rng(929)
df_qr = pd.DataFrame({
"X1": rng.normal(0, 1, N_qr),
"X2": rng.normal(0, 1, N_qr)
})
df_qr["Y"] = -0.5 + -2 * df_qr["X1"] + 1.9 * df_qr["X1"] ** 3 + df_qr["X2"] - 0.4 * df_qr["X2"] **4 + rng.normal(0, 1, N_qr)
tic = time.time()
fit_qr = pf.quantreg(
fml = "Y ~ X1 + X2",
data = df_qr,
quantile = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9],
method = "pfn",
multi_method = "cfm2"
)
toc = time.time()
print(f"Fit the entire quantile regression process with {N_qr} obs and k = 3 in {np.round(toc-tic)} seconds.")
pf.qplot(fit_qr, figsize = [7,3])-
We have switched the default solver to
scipy.linalg.solve(): link -
You can now set the maximum number of iterations for the demeaning algo via a
fixef_maxiterargument: link
Bug Fixes
- We fixed a bug in internal renaming of categoricals: link
- We fixed a bug in etable arguments link
- We stopped casting dependent variable to integer to void Information Loss in Poisson Regression: link
Documentation
- We have added a guide on how to replicate Stata results with pyfixest: link
- We improved the documentation on how to relabel variable names in the plotting and etable functions: link
Infrastructure
- We have reorganized our tests and rely more on conda environments for making R package test dependencies available: link
Community
- We have added a Code of Conduct.
- We have opened our discord community. Please join us there to discuss pyfixest and other py-econometrics projects! Link here.
Full Changelog
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci in #876
- add gd link to readme by @s3alfisc in #881
- Update README.md by @s3alfisc in #882
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci in #883
- Code of Conduct by @s3alfisc in #879
- renaming categories without T. notation by @FuZhiyu in #886
- docs: add FuZhiyu as a contributor for bug, and code by @allcontributors in #888
- Bug fix in etable arguments by @dsliwka in #889
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci in #893
- update in labels: adding comment on the role of _coefname by @mortizm1988 in #895
- docs: add mortizm1988 as a contributor for doc by @allcontributors in #896
- #890 - Show how to replicate Stata results by @jestover in #897
- docs: add jestover as a contributor for doc by @allcontributors in #898
- small updates to docs by @s3alfisc in #899
- Prevent Casting Dependent Variable to Integer to Avoid Information Loss in Poisson Regression by @JaapCTJ in #900
- docs: add JaapCTJ as a contributor for code by @allcontributors in #903
- Switch default solver to scipy.linalg.solve() [#846 issue] by @AronNemeth in #904
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci in #902
- Reorganize Tests against R by @shapiromh in #906
- docs: add shapiromh as a contributor for code by @allcontributors in #907
- add an example for etable by @mortizm1988 in #909
- Rust by @schroedk in #905
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci in #918
- Implement Rust Backend by @s3alfisc in #878
- docs: add schroedk as a contributor for code by @allcontributors in #926
- discord to readme by @s3alfisc in #931
- small update to readme by @s3alfisc in #932
- thanks to the aaii team! by @s3alfisc in #934
- chore(license): add MIT SPDX headers and permission record for fixest-derived code by @s3alfisc in #935
- fix logo by @s3alfisc in #936
- Quantile Regression by @s3alfisc in #908
- qreg in readme by @s3alfisc in #939
- remove i_ref1 by @WiktorTheScriptor in #938
- docs: add WiktorTheScriptor as a contributor for code by @allcontributors in #940
- Issue933 - added the ability to customize the maximum iterations for the demeaning algorithm by @damandhaliwal in #944
- docs: add damandhaliwal as a contributor for code by @allcontributors in #946
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci in #925
- add citation to readme by @s3alfisc in #947
- Implements "preprocessing frisch newton" algorithm by @s3alfisc in #941
- prepare changelog for v0.30 release by @s3alfisc in #949
- PyFixest version 0.30.0 by @s3alfisc in #950
- Move to pyo3 0.24.1 by @s3alfisc in #951
New Contributors
- @FuZhiyu made their first contribution in #886
- @mortizm1988 made their first contribution in #895
- @jestover made their first contribution in #897
- @JaapCTJ made their first contribution in #900
- @shapiromh made their first contribution in #906
- @schroedk made their first contribution in #905
- @WiktorTheScriptor made their first contribution in #938
- @damandhaliwal made their first contribution in #944
Full Changelog: v0.29.0...v0.30.0
