Exporting and persisting results¶
import numpy as np
import pandas as pd
import statsmodels.api as sm
import statsmodels.formula.api as smf
from pymargins import Margins
rng = np.random.default_rng(42)
n = 2000
df = pd.DataFrame({
"age": rng.integers(20, 75, n),
"female": rng.binomial(1, 0.52, n),
})
lp = -1.5 + 0.04 * df["age"] - 0.3 * df["female"]
df["y"] = rng.binomial(1, 1 / (1 + np.exp(-lp)))
fit = smf.glm("y ~ age + female", data=df,
family=sm.families.Binomial()).fit()
m = Margins.log_scale(fit, at="overall")
Every MarginsResult can be printed, framed, or serialized to LaTeX
/ HTML for inclusion in papers and reports.
res = m.dydx("age", atexog={"female": [0, 1]})
print(res.summary(stars=True)) # text table with significance stars
res.to_frame() # pandas.DataFrame
print(res.to_latex()) # LaTeX tabular
print(res.to_html()) # HTML <table>
=========================================================================
Margins Result (delta, level=0.95)
=========================================================================
estimate std err z P>|z| [95% Conf. Int.]
-------------------------------------------------------------------------
female=[0, 1], age 0.0090*** 0.0711 -66.1769 0.000 0.0079, 0.0104
=========================================================================
n = 2000
Note: std err is on the inference scale; estimate and CI are on the reporting scale.
κ: 0.079
Delta-vs-sim disagreement: 3.503%
\begin{tabular}{lrrrr}
\hline
\hline
& estimate & std err & z & P>|z| & [95\% Conf. Int.] \\
\hline
female=[0, 1], age & 0.0090 & 0.0711 & -66.1769 & 0.000 & 0.0079, 0.0104 \\
\hline
\hline
\end{tabular}
<table class="pymargins-result">
<thead>
<tr><th></th><th>estimate</th><th>std err</th><th>z</th><th>P>|z|</th><th>[95% Conf. Int.]</th></tr>
</thead>
<tbody>
<tr><td>female=[0, 1], age</td><td>0.0090</td><td>0.0711</td><td>-66.1769</td><td>0.000</td><td>0.0079, 0.0104</td></tr>
</tbody>
</table>
Saving to CSV, Excel, or Parquet¶
to_frame() returns a tidy pandas.DataFrame, so any pandas export
works out of the box:
df = res.to_frame()
df.to_csv("ame_results.csv", index=False)
df.to_excel("ame_results.xlsx", index=False)
df.to_parquet("ame_results.parquet")
The DataFrame includes scenario columns (e.g. age, female) when
available, making it ready for downstream plotting or reporting
without string parsing.
Long-term storage with to_disk / from_disk¶
For checkpointing or sharing results between scripts, use the built-in pickle persistence methods. They automatically materialize the result (so the saved object is self-contained) and include a version check on load:
# Save
res.to_disk("ame_results.pkl")
# Load in another session
from pymargins import MarginsResult
loaded = MarginsResult.from_disk("ame_results.pkl")
print(loaded.summary())
=======================================================
Margins Result (delta, level=0.95)
=======================================================
estimate std err [95% Conf. Int.]
-------------------------------------------------------
female=[0, 1], age 0.0090 0.0711 0.0079, 0.0104
=======================================================
n = 2000
Note: std err is on the inference scale; estimate and CI are on the reporting scale.
κ: 0.079
Delta-vs-sim disagreement: 3.503%
/home/hunter/Workspace/pymargins/pymargins/_result/_margins.py:271: UserWarning: Test statistics omitted from summary: Cannot run test: result has neither gradient nor draws.
rows = self._summary_rows()
Materialised results support .summary(), .to_frame(), .to_latex(),
and .to_html(), but they cannot recompute CIs at new confidence
levels or run new hypothesis tests because the gradient and session
reference are dropped during materialisation.
In-memory slimming with materialize¶
If you only need to reduce memory inside a single Python session (e.g.
when accumulating many results in a loop), call materialize() directly:
slim = res.materialize() # estimates/SE/CI only; drops gradients
print(slim.summary())
=======================================================
Margins Result (delta, level=0.95)
=======================================================
estimate std err [95% Conf. Int.]
-------------------------------------------------------
female=[0, 1], age 0.0090 0.0711 0.0079, 0.0104
=======================================================
n = 2000
Note: std err is on the inference scale; estimate and CI are on the reporting scale.
κ: 0.079
Delta-vs-sim disagreement: 3.503%
Materialised results still support arithmetic (+, -, *, /,
.scaled(by=...)) for post-hoc combination. The only thing you lose
is the ability to call .conf_int(level=...) when the original
session used the delta method (recomputing CIs at new levels requires
the gradient, which is dropped).