---
jupytext:
text_representation:
extension: .md
format_name: myst
format_version: 0.13
kernelspec:
display_name: Python 3
language: python
name: python3
---
# Exporting and persisting results
```{code-cell} python
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.
```{code-cell} python
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
```
## Saving to CSV, Excel, or Parquet
`to_frame()` returns a tidy `pandas.DataFrame`, so any pandas export
works out of the box:
```{code-cell} python
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:
```{code-cell} python
# 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())
```
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:
```{code-cell} python
slim = res.materialize() # estimates/SE/CI only; drops gradients
print(slim.summary())
```
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).