Skip to main content

Fast econometric regressions for Python — OLS, IV, panel, probit/logit with robust and clustered SEs, built on Polars and Rust

Project description

polars_reg

Fast econometric regressions for Python, built on Polars and Rust. Covers OLS, IV, panel, and limited-dependent-variable models with robust and clustered standard errors — validated against Stata and R to 5+ decimal places. Also accepts pandas DataFrames.

The computational backend is written in Rust (via PyO3), with parallel demeaning and sandwich estimators powered by Rayon. On fixed-effects and clustered models, polars_reg matches or beats R/fixest and is 2–8× faster than statsmodels, pyfixest, and linearmodels.

Features

Regression Estimators

  • OLS / WLS — analytic weights (weights=) and frequency weights (fweights=)
  • High-dimensional fixed effects — reghdfe-style absorption via iterative demeaning
  • 2SLS / IV with first-stage F-statistics and weak instrument diagnostics
  • LIML — limited information maximum likelihood
  • GMM-IV — two-step efficient GMM with Hansen J test
  • Panel: fixed effects (within), random effects (Swamy-Arora GLS), first-difference
  • Dynamic panel GMM: Arellano-Bond (difference GMM) and Blundell-Bond (system GMM)
  • Probit / Logit — MLE with marginal effects and odds ratios
  • Quantile regression — median and arbitrary quantiles via IRLS
  • PPML — Poisson pseudo-maximum likelihood for count/gravity models

Standard Errors

  • Robust — HC0, HC1 (Stata's robust), HC2, HC3
  • Clustered — one-way and multi-way (Cameron-Gelbach-Miller)
  • HAC — Newey-West for time series
  • Driscoll-Kraay — robust to cross-sectional dependence in panels
  • Bootstrap — pairs bootstrap and wild cluster bootstrap (Webb 6-point)

Convenience Features

  • GroupBy regression — run any estimator per group (e.g., per stock or industry)
  • regtable — side-by-side regression tables (estout/esttab-style) with LaTeX and HTML export
  • Coefficient plots and added-variable plots via Altair
  • Diagnostics — Wald test, Hausman test (FE vs RE), Kleibergen-Paap, Stock-Yogo weak IV
  • Formula API with interaction terms (x1*x2, x1:x2) and indicator expansion (i.group)

Validation

  • Stata equivalenceto_stata() generates the matching Stata command for any specification
  • R equivalenceto_r() generates the matching fixest/lm call
  • Automated comparisoncompare_stata() and compare_r() run the command and diff coefficients

Performance

Benchmarks

Wall-clock time across dataset sizes (1K–1M rows), compared to statsmodels, pyfixest, linearmodels, R/fixest, and Stata:

  • Plain OLS: statsmodels is faster below ~100K rows due to lower call overhead
  • FE, IV, and clustered models: polars_reg is consistently faster than other Python packages, especially at smaller N
  • At large N: performance converges with R/fixest — the difference between the two is roughly negligible

Reproduce with python benchmarks/generate_chart.py (requires R with fixest; Stata optional).

Installation

pip install polars_reg

Quick Start

import polars as pl
import polars_reg as pr

df = pl.read_csv("data.csv")

# OLS with robust standard errors
result = pr.ols("y ~ x1 + x2 + x3", data=df, vcov="HC1")
print(result.summary())

# OLS with absorbed fixed effects and clustered SEs (like Stata's reghdfe)
result = pr.ols("y ~ x1 + x2 | firm_id + year_id", data=df, cluster=["firm_id"])

# IV / 2SLS
result = pr.iv2sls("y ~ x_exog || x_endog ~ z1 + z2", data=df)

# Panel fixed effects
result = pr.panel_fe("y ~ x1 + x2", data=df, entity="firm_id", time="year_id")

# GroupBy: run regression per industry
grp = pr.groupby_reg(pr.ols, "y ~ x1 + x2", df, group_by="industry")
grp.coef_table()  # stacked Polars DataFrame

# Side-by-side comparison table
pr.regtable(m1, m2, m3, labels=["OLS", "Robust", "FE"])

# Probit / Logit
result = pr.logit("y_binary ~ x1 + x2", data=df, cluster="firm_id")
pr.marginal_effects(result, at="mean")
pr.odds_ratios(result)

# Quantile regression (median)
result = pr.quantreg("y ~ x1 + x2", data=df, tau=0.5)

# Dynamic panel GMM
result = pr.panel_ab("y ~ x1", data=df, entity="firm_id", time="year_id")
result = pr.panel_sys_gmm("y ~ x1", data=df, entity="firm_id", time="year_id")

# PPML (Poisson / gravity model)
result = pr.ppml("count ~ x1 + x2", data=df, cluster=["firm_id"])

# Coefficient plot (interactive Altair chart)
result.coefplot()
pr.coefplot(m1, m2, m3, labels=["OLS", "IV", "FE"])

# Added-variable (partial regression) plot
result.avplot("x1")

# Out-of-sample prediction
preds = result.predict(new_df)
intervals = result.predict_interval(new_df, alpha=0.05)  # fit, se, lower, upper

# Access results
result.coefficients  # coefficient vector
result.se            # standard errors
result.tstat         # t-statistics
result.pvalue        # p-values
result.confint()     # confidence intervals
result.coef_table()  # Polars DataFrame
result.wald_test(R)  # Wald test for linear restrictions
result.predict(new_df)   # out-of-sample predictions
result.coefplot()        # coefficient plot
result.avplot()          # added-variable plots

Formula Syntax

Formula Meaning Stata R
y ~ x1 + x2 OLS reg y x1 x2 lm(y ~ x1 + x2)
y ~ x1 + x2 - 1 No intercept reg y x1 x2, noconstant lm(y ~ x1 + x2 - 1)
y ~ x1 | fe1 + fe2 Absorbed FE reghdfe y x1, absorb(fe1 fe2) feols(y ~ x1 | fe1 + fe2)
y ~ x1 || x_end ~ z1 + z2 IV/2SLS ivregress 2sls y x1 (x_end = z1 z2) feols(y ~ x1 | 0 | x_end ~ z1 + z2)
y ~ x1 | fe1 | x_end ~ z1 IV + FE ivreghdfe y x1 (x_end = z1), absorb(fe1) feols(y ~ x1 | fe1 | x_end ~ z1)
y ~ x1*x2 Full factorial reg y c.x1##c.x2 lm(y ~ x1 * x2)
y ~ x1:x2 Interaction only reg y c.x1#c.x2 lm(y ~ x1:x2)
y ~ i.group + x1 Indicator dummies reg y i.group x1 lm(y ~ factor(group) + x1)
y ~ i.group*x1 Indicator × continuous reg y i.group#c.x1 lm(y ~ factor(group) * x1)

Estimators

Function Description
ols() OLS/WLS with optional FE absorption
iv2sls() Two-stage least squares
liml() Limited information maximum likelihood
gmm_iv() Two-step efficient GMM
panel_fe() Panel fixed effects (within)
panel_re() Panel random effects (Swamy-Arora GLS)
panel_fd() Panel first-difference
panel_ab() Arellano-Bond dynamic panel GMM
panel_sys_gmm() Blundell-Bond system GMM
probit() Probit MLE
logit() Logit MLE
quantreg() Quantile regression (IRLS + bootstrap)
ppml() Poisson pseudo-maximum likelihood
coefplot() Coefficient plot with CIs (Altair)
groupby_reg() Run any estimator per group
regtable() Side-by-side regression table
marginal_effects() Probit/logit marginal effects
odds_ratios() Logit odds ratios with delta-method SEs
hausman_test() Hausman specification test (FE vs RE)

Standard Error Options

  • vcov="iid" — homoskedastic (default)
  • vcov="HC1" — heteroskedasticity-robust (Stata's robust)
  • vcov="HC0", "HC2", "HC3" — other HC variants
  • cluster=["firm_id"] — one-way clustered
  • cluster=["firm_id", "year_id"] — two-way clustered (Cameron-Gelbach-Miller)
  • vcov="NW" — Newey-West HAC (requires time=)
  • vcov="DK" — Driscoll-Kraay (requires time=)
  • vcov="bootstrap" — pairs bootstrap
  • vcov="wildboot" — wild cluster bootstrap (requires cluster=)

Stata / R Equivalence

Generate equivalent code to verify results in Stata or R:

# Stata code
print(pr.to_stata("ols", "y ~ x1 + x2 | firm_id", cluster=["firm_id"]))
# → reghdfe y x1 x2, absorb(firm_id) vce(cluster firm_id)

# R code
print(pr.to_r("ols", "y ~ x1 + x2 | firm_id", cluster=["firm_id"]))
# → library(fixest)
#   model <- feols(y ~ x1 + x2 | firm_id, data=df, vcov=~firm_id)

Documentation

  • Showcase notebook — full tour of all features (rendered PDF)
  • API reference — generate locally with uv run pdoc polars_reg --docformat google (serves at http://localhost:8080), or build static HTML with uv run pdoc polars_reg -o docs/api --docformat google

Requirements

  • Python >= 3.11
  • Polars >= 1.0
  • NumPy >= 1.24
  • SciPy >= 1.10
  • pandas (optional — for pandas DataFrame input)
  • Altair (optional — for plotting)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

polars_reg-0.1.2.tar.gz (1.3 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

polars_reg-0.1.2-cp312-cp312-win_amd64.whl (406.4 kB view details)

Uploaded CPython 3.12Windows x86-64

polars_reg-0.1.2-cp312-cp312-macosx_11_0_arm64.whl (487.4 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

polars_reg-0.1.2-cp312-cp312-macosx_10_12_x86_64.whl (517.9 kB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

polars_reg-0.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (575.5 kB view details)

Uploaded CPython 3.8manylinux: glibc 2.17+ x86-64

File details

Details for the file polars_reg-0.1.2.tar.gz.

File metadata

  • Download URL: polars_reg-0.1.2.tar.gz
  • Upload date:
  • Size: 1.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for polars_reg-0.1.2.tar.gz
Algorithm Hash digest
SHA256 61fc3296f5c7c5d80c16c11b594a3979eebd7b9aca90e5b8b1709267ada17e2e
MD5 0fdc12562ccde0263ad1b60f56719f2f
BLAKE2b-256 7b5f8a941bc0a1ef0ce17d940239877bd88c9736bf603db8e9e8b3ad82c91c99

See more details on using hashes here.

Provenance

The following attestation bundles were made for polars_reg-0.1.2.tar.gz:

Publisher: ci.yml on AlexSulliMora/polars_reg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file polars_reg-0.1.2-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: polars_reg-0.1.2-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 406.4 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for polars_reg-0.1.2-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 91eaf9edb7b1225a0a34487055471ded1ce97f6be7f72df558b9cdcf1fa7981d
MD5 4ce97aff29365c5b7f1fc112dfa4e06e
BLAKE2b-256 e1fb4330f87a7a4b712efcbcd4c66922e474e489df3eb3a7979f7a842cce19c8

See more details on using hashes here.

Provenance

The following attestation bundles were made for polars_reg-0.1.2-cp312-cp312-win_amd64.whl:

Publisher: ci.yml on AlexSulliMora/polars_reg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file polars_reg-0.1.2-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for polars_reg-0.1.2-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6291a72e76d2044c3822c1a49d99e5121e307096918755a6440429200db0c19d
MD5 3cc65dbc069e0d58fa1e68c1da3d3e46
BLAKE2b-256 026385f69d71481c8d4c826d4b6d830ad8466331471d0c49f69cb50c53f63d37

See more details on using hashes here.

Provenance

The following attestation bundles were made for polars_reg-0.1.2-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: ci.yml on AlexSulliMora/polars_reg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file polars_reg-0.1.2-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for polars_reg-0.1.2-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 a5f079c416e285f927cb2fe2f2ee9dcf837ab5062fea83a8e73cd1511f2a17aa
MD5 dd52a6a71dc50342cd6ec1f09800fd0a
BLAKE2b-256 60c7b62dbef4be4ecc729c1b5ff57ed75301961e0862a2b5e9fb1829d7d7f0d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for polars_reg-0.1.2-cp312-cp312-macosx_10_12_x86_64.whl:

Publisher: ci.yml on AlexSulliMora/polars_reg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file polars_reg-0.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for polars_reg-0.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4b3174b38943f24c247874fec7ac806bcfff5f278fedb8297573bbb452b83266
MD5 c03c87b34a236fb65cf60b388867a3a3
BLAKE2b-256 7bafafabf63e0582a7545ad0869e2a775e63e1d66d120000126d7e860c8e653f

See more details on using hashes here.

Provenance

The following attestation bundles were made for polars_reg-0.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: ci.yml on AlexSulliMora/polars_reg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page