Introduction¶
smmargins is a small module that fills in the marginal-effects gaps
in StatsModels: adjusted predictions
and marginal effects at user-specified covariate profiles, with
delta-method standard errors, for any fitted model that exposes
params, cov_params(), and a predict(params, exog) method.
The design target is Stata’s margins command:
the same statistics, the same parameter names where they translate, and
the same answers to the precision both tools agree on.
Why another margins module?¶
StatsModels ships Results.get_margeff, but it is limited:
only marginal effects, not adjusted predictions;
atexogis keyed by column index, not variable name;no
at(...)profiles, no representative-value contrasts;no joint covariance across statistics, so you cannot form contrasts like a difference-in-differences without re-deriving the delta method by hand;
no support for difference-in-differences on the response scale (the Ai & Norton 2003 issue).
Installation¶
pip install smmargins
Requires Python ≥3.9. Dependencies (numpy, pandas,
statsmodels, scipy, patsy) are installed automatically.
Quickstart¶
import statsmodels.formula.api as smf
from smmargins import Margins
fit = smf.logit(
"voted ~ age + income + C(educ) + female + age:female",
data=df,
).fit()
M = Margins(fit)
# Adjusted predictions
M.predict() # AAP
M.predict(at="mean") # APM (margins, atmeans)
M.predict(atexog={"age": [25, 45, 65]}) # APR
# Marginal effects on the response (probability) scale
M.dydx("age") # AME
M.dydx("age", at="mean") # MEM
M.dydx("age", atexog={"female": [0, 1]}) # MER, by sex
M.dydx("educ", reference="college") # discrete contrasts
# Difference-in-differences on the response scale
res = M.did("group", "preexist_Y",
group_levels=["A", "B"], condition_levels=[0, 1])
print(res) # cells, simple effects, DiD
# Alternative VCEs and robust covariance
M.dydx("age", cov_type="HC3") # heteroskedastic-robust
M.dydx("age", vce="simulation", n_sims=2000,
sim_seed=0) # Krinsky–Robb
M.dydx("age", vce="bootstrap", n_boot=1000,
boot_seed=0) # pairs bootstrap
# Simultaneous CIs across a family of three predictions
M.predict(atexog={"age": [25, 45, 65]},
vce="simulation", n_sims=4000,
ci_method="sup-t")
Each call returns a MarginsResult with .estimate,
.se, .vcov, .ci_lower, .ci_upper, .pvalue, plus
.summary() returning a pandas.DataFrame. Pass use_t=True
to the Margins constructor for t-distribution
inference (uses results.df_resid).
Observation weights¶
Pass weights at construction. weight_type="sampling" (default) or
"frequency". WLS-fitted results respect their fit-time weights when
weights=None; explicit weights= overrides and warns. Bootstrap
resampling uses weight-proportional draws under sampling weights.
M = Margins(fit, weights=w)
M = Margins(fit, weights=counts, weight_type="frequency")
Where to next¶
Tutorials — learn by doing.
Tutorial 1: Getting Started with smmargins — install, fit, first AAP and AME.
Tutorial 2: Adjusted Predictions at Different Points —
at=,atexog=, scales.Tutorial 3: Marginal Effects — continuous, discrete, elasticities.
Tutorial 4: Inference and Standard Errors — delta vs KR vs bootstrap, simultaneous CIs.
Tutorial 5: Difference-in-Differences — 2x2 difference-in-differences end-to-end.
Tutorial 6: Counterfactual Predictions and Plotting —
newdata=,Expr, the plotting API.
How-to guides — task-focused recipes.
Robust covariance: How to compute robust and cluster-robust standard errors for marginal effects.
Alternative VCEs: How to use Krinsky–Robb simulation for standard errors and confidence intervals, How to compute bootstrap standard errors with pairs, cluster, or block resampling, How to compute simultaneous confidence intervals for families of margins.
Multi-outcome models: How to compute marginal effects for multinomial and ordered outcome models.
Subgroup AMEs and joint tests: How to compute subgroup-specific average marginal effects with the over parameter, How to perform joint Wald tests and pairwise comparisons on marginal effects.
Custom scales: How to report marginal effects on custom scales and with user-defined transforms, How to compute elasticities and semi-elasticities for marginal effects.
Counterfactuals and plotting: How to compute counterfactual predictions with values, Expr, and newdata, How to set covariate profiles with values=, Expr, and newdata=, How to plot predictions, slopes, and comparisons.
Validation and modes: How to verify smmargins results against R marginaleffects, How to choose between formula mode and raw exog mode.
Explanations — theory and design.
Mathematical motivation — delta method, statistic schema, analytic vs FD Jacobian.
Prediction Scales and Link Functions, Discrete vs. Continuous Variable Detection, Analytic vs. Finite-Difference Jacobians.
Why Patsy Design Matrix Rebuilding Matters, Formula Mode vs. Raw Exog Mode, Why Expr and the values= DSL.
Comparing Inference Methods: Delta vs. KR vs. Bootstrap, Multiple Comparison Adjustments, Why Margins.contrast exists: joint covariance for two arms.
The Ai & Norton Difference-in-Differences Problem — why DiD belongs on the response scale.
Reference.
API reference — every public class and method.
Demos — full Williams-style and DiD walkthroughs from the repository root.