PyFixest
is a Python clone of the excellent fixest package. The package aims to mimic fixest
syntax and functionality as closely as Python allows. For a quick introduction, see the tutorial.
At the moment, PyFixest
supports
- OLS and IV Regression
- Poisson Regression
- Multiple Estimation Syntax
- Several Robust and Cluster Robust Variance-Covariance Types
- Wild Cluster Bootstrap Inference (via wildboottest)
- Difference-in-Difference Estimators:
- Gardner's two-stage ("
Did2s
") estimator is available via thepyfixest.experimental.did
module
- Gardner's two-stage ("
You can install the release version from PyPi
by running pip install pyfixest
or the development version from github.
All benchmarks follow the fixest benchmarks. All non-pyfixest timings are taken from the fixest
benchmarks.
PyFixest
0.10.8 adds experimental support for Gardner's two stage "DID2s" estimator:
import pandas as pd
import numpy as np
from pyfixest.experimental.did import did2s
from pyfixest.estimation import feols
from pyfixest.visualize import iplot
# download csv from this repo
df_het = pd.read_csv("https://raw.githubusercontent.com/s3alfisc/pyfixest/master/pyfixest/experimental/data/df_het.csv")
fit = did2s(
df_het,
yname = "dep_var",
first_stage = "~ 0 | state + year",
second_stage = "~i(rel_year)",
treatment = "treat",
cluster = "state",
i_ref1 = [-1.0, np.inf],
)
fit_twfe = feols(
"dep_var ~ i(rel_year) | state + year",
df_het,
i_ref1 = [-1.0, np.inf]
)
iplot([fit, fit_twfe], coord_flip=False, figsize = (900, 400), title = "TWFE vs DID2S")
from pyfixest.estimation import feols
from pyfixest.utils import get_data
data = get_data()
# OLS Estimation
fit = feols("Y~X1 | csw0(f1, f2)", data = data, vcov = {'CRV1':'group_id'})
fit.summary()
# ###
#
# Model: OLS
# Dep. var.: Y
# Inference: CRV1
# Observations: 998
#
# | Coefficient | Estimate | Std. Error | t value | Pr(>|t|) | 2.5 % | 97.5 % |
# |:--------------|-----------:|-------------:|----------:|-----------:|--------:|---------:|
# | Intercept | 2.206 | 0.078 | 28.304 | 0.000 | 2.043 | 2.370 |
# | X1 | 0.358 | 0.051 | 6.962 | 0.000 | 0.250 | 0.466 |
# ---
# RMSE: 1.765 Adj. R2: 0.024 Adj. R2 Within: 0.024
# ###
#
# Model: OLS
# Dep. var.: Y
# Fixed effects: f1
# Inference: CRV1
# Observations: 997
#
# | Coefficient | Estimate | Std. Error | t value | Pr(>|t|) | 2.5 % | 97.5 % |
# |:--------------|-----------:|-------------:|----------:|-----------:|--------:|---------:|
# | X1 | 0.411 | 0.040 | 10.188 | 0.000 | 0.326 | 0.495 |
# ---
# RMSE: 1.421 Adj. R2: 0.048 Adj. R2 Within: 0.048
# ###
#
# Model: OLS
# Dep. var.: Y
# Fixed effects: f1+f2
# Inference: CRV1
# Observations: 997
#
# | Coefficient | Estimate | Std. Error | t value | Pr(>|t|) | 2.5 % | 97.5 % |
# |:--------------|-----------:|-------------:|----------:|-----------:|--------:|---------:|
# | X1 | 0.431 | 0.035 | 12.319 | 0.000 | 0.358 | 0.505 |
# ---
# RMSE: 1.2 Adj. R2: 0.07 Adj. R2 Within: 0.07
Standard Errors can be adjusted after estimation, "on-the-fly":
fit1 = fit.fetch_model(0)
fit1.vcov("hetero").tidy()
# Model: Y~X1
# ###
#
# Model: OLS
# Dep. var.: Y
# Inference: hetero
# Observations: 998
#
# | Coefficient | Estimate | Std. Error | t value | Pr(>|t|) | 2.5 % | 97.5 % |
# |:--------------|-----------:|-------------:|----------:|-----------:|--------:|---------:|
# | Intercept | 2.206 | 0.088 | 25.180 | 0.000 | 2.034 | 2.378 |
# | X1 | 0.358 | 0.068 | 5.254 | 0.000 | 0.224 | 0.491 |
# ---
# RMSE: 1.765 Adj. R2: 0.024 Adj. R2 Within: 0.024
Last, PyFixest
also supports IV estimation via three part formula syntax:
fit_iv = feols("Y ~ 1 | f1 | X1 ~ Z1", data = data)
fit_iv.summary()
# ###
#
# Model: IV
# Dep. var.: Y
# Fixed effects: f1
# Inference: CRV1
# Observations: 997
#
# | Coefficient | Estimate | Std. Error | t value | Pr(>|t|) | 2.5 % | 97.5 % |
# |:--------------|-----------:|-------------:|----------:|-----------:|--------:|---------:|
# | X1 | 0.479 | 0.096 | 4.979 | 0.000 | 0.282 | 0.676 |
# ---