Skip to content

statspai.postestimation

postestimation

Post-estimation tools for StatsPAI.

Provides: - margins(): Average Marginal Effects (AME), Marginal Effects at the Mean (MEM) - marginsplot(): Visualize marginal effects - test(): Wald / F test for linear restrictions (beta1 = beta2, joint significance) - lincom(): Linear combinations of coefficients with inference

Equivalent to Stata's margins, test, lincom commands.

margins_table

margins_table(result, data: Optional[DataFrame] = None, variables: Optional[List[str]] = None, at: Optional[Dict[str, Any]] = None, method: str = 'ame', eps: float = 1e-05, alpha: float = 0.05)

Marginal-effects result that pipes straight into sp.regtable.

Thin adapter over :func:margins: computes the marginal effects (same kwargs), then wraps the resulting DataFrame in a :class:_MarginsResult exposing params / std_errors / tvalues / pvalues / conf_int_* so that sp.regtable(margins_table(model)) produces a publication-quality marginal-effects table — closing the "estimator → margins table" gap that previously required users to hand-build add_rows.

Mirrors the R workflow modelsummary(avg_slopes(model)).

Parameters:

Name Type Description Default
result EconometricResults

Fitted model — same input sp.margins accepts.

required
data Optional[DataFrame]

Forwarded verbatim to :func:margins.

None
variables Optional[DataFrame]

Forwarded verbatim to :func:margins.

None
at Optional[DataFrame]

Forwarded verbatim to :func:margins.

None
method Optional[DataFrame]

Forwarded verbatim to :func:margins.

None
eps Optional[DataFrame]

Forwarded verbatim to :func:margins.

None
alpha Optional[DataFrame]

Forwarded verbatim to :func:margins.

None

Returns:

Type Description
_MarginsResult

A duck-typed result object usable directly as a positional argument to :func:sp.regtable.

Examples:

>>> import statspai as sp
>>> m = sp.logit("y ~ x + z", data=df)
>>> mt = sp.margins_table(m)
>>> sp.regtable(mt, output="latex", filename="margins.tex")

event_study_table

event_study_table(result, *, regex: Optional[str] = None, label_fmt: str = 't={t}', include_reference: bool = False)

Adapter that turns an event-study fit into a regtable input.

Two extraction paths:

  1. CausalResult fast path — when result.model_info carries an "event_study" DataFrame (the canonical shape produced by :func:sp.event_study), read its relative_time / estimate / se / ci_lower / ci_upper / pvalue columns directly. Reference period (estimate==0 and se==0) is dropped by default (set include_reference=True to keep it visible).

  2. Regex path — when regex is provided, scan result.params.index for coefficients matching the pattern and use the first capture group as the relative time.

Rows are sorted by relative time (so the rendered table reads t=-3, t=-2, …, t=+3 regardless of the underlying coefficient name encoding).

Parameters:

Name Type Description Default
result CausalResult or EconometricResults

Fitted model. The CausalResult fast path is used automatically when model_info['event_study'] is present.

required
regex str

Pattern with one capture group that matches the relative time in coefficient names. Required when the CausalResult fast path is not applicable. Examples: r"^tau_(-?\d+)$", r"^lag(\d+)$", r"::(-?\d+)$".

None
label_fmt str

Format string for the row label of each event-time bin. The {t} placeholder receives the integer relative time.

``"t={t}"``
include_reference bool

Whether to render the reference period row (typically t=-1) where the estimate is identically zero.

False

Returns:

Type Description
_MarginsResult

Duck-typed result accepted directly by :func:sp.regtable.

Examples:

>>> r = sp.event_study(panel, y="y", treat_time="treat_time",
...                    time="time", unit="unit", window=(-3, 3))
>>> sp.regtable(sp.event_study_table(r), title="Event study")

marginsplot

marginsplot(margins_df: DataFrame, ax=None, figsize: tuple = (8, 5), color: str = '#2C3E50', title: Optional[str] = None)

Plot marginal effects with confidence intervals.

Parameters:

Name Type Description Default
margins_df DataFrame

Output from margins().

required
ax matplotlib Axes
None
figsize tuple
(8, 5)
color str
'#2C3E50'
title str
None

Returns:

Type Description
(fig, ax)

margins_at

margins_at(result, data: DataFrame, at: Dict[str, Any], alpha: float = 0.05) -> DataFrame

Compute predictive margins at specific covariate values.

Equivalent to Stata's margins, at(experience=(1 5 10 15 20)).

For each combination of at values, every observation has the at variables set to those values while all other covariates stay at their observed levels. The predicted value is averaged across observations to give the predictive margin at that point, with delta-method SEs.

Parameters:

Name Type Description Default
result EconometricResults

Fitted model result (must have .params and associated data).

required
data DataFrame

Data to compute margins on.

required
at dict

Mapping of variable names to lists/arrays of values. If multiple variables are given, the Cartesian product of all value lists is used. Example::

at={"experience": [1, 5, 10], "female": [0, 1]}

produces 6 grid points.

required
alpha float

Significance level for confidence intervals.

0.05

Returns:

Type Description
DataFrame

One row per grid point with columns for each at variable, plus margin, se, ci_lower, ci_upper.

Examples:

>>> result = sp.regress("wage ~ experience + female + experience:female", data=df)
>>> m = sp.margins_at(result, data=df, at={"experience": [1, 5, 10, 15, 20]})
>>> sp.margins_at_plot(m)

margins_at_plot

margins_at_plot(margins_at_df: DataFrame, x: Optional[str] = None, by: Optional[str] = None, ax=None, figsize: tuple = (8, 5), title: Optional[str] = None, xlabel: Optional[str] = None, ylabel: str = 'Predicted Value', palette: Optional[List[str]] = None)

Plot predictive margins from margins_at() with confidence bands.

Parameters:

Name Type Description Default
margins_at_df DataFrame

Output from margins_at().

required
x str

Variable to place on the x-axis. If None, inferred as the at-variable with the most unique values.

None
by str

Variable to produce separate lines for (legend grouping).

None
ax matplotlib Axes
None
figsize tuple
(8, 5)
title str
None
xlabel str
None
ylabel str
'Predicted Value'
palette list of str

Colours for each by group.

None

Returns:

Type Description
(fig, ax)

contrast

contrast(result, data: DataFrame, variable: str, method: str = 'r', reference: Any = None, alpha: float = 0.05) -> DataFrame

Compute contrasts of predictive margins across levels of a variable.

Equivalent to Stata's margins <var>, contrast(ar) / contrast(r).

Parameters:

Name Type Description Default
result EconometricResults

Fitted model result.

required
data DataFrame

Estimation data.

required
variable str

Categorical variable whose levels are contrasted.

required
method str

Contrast type:

  • 'r' (reference): each level vs reference level.
  • 'ar' (adjacent): each level vs the previous level.
  • 'gw' (grand-mean weighted): each level vs the weighted grand mean of all levels.
'r'
reference scalar

Reference level when method='r'. Defaults to the smallest observed level.

None
alpha float

Significance level.

0.05

Returns:

Type Description
DataFrame

Columns: contrast_label, contrast, se, z, pvalue, ci_lower, ci_upper.

Examples:

>>> result = sp.regress("wage ~ C(education) + experience", data=df)
>>> sp.contrast(result, data=df, variable="education", method="r", reference=0)

pwcompare

pwcompare(result, data: DataFrame, variable: str, adjust: str = 'none', alpha: float = 0.05) -> DataFrame

Pairwise comparisons of predictive margins across all levels.

Equivalent to Stata's pwcompare <var>.

Parameters:

Name Type Description Default
result EconometricResults

Fitted model result.

required
data DataFrame

Estimation data.

required
variable str

Categorical variable whose levels are compared pairwise.

required
adjust str

P-value adjustment method:

  • 'none': unadjusted.
  • 'bonferroni': Bonferroni correction.
  • 'sidak': Sidak correction.
  • 'holm': Holm step-down procedure.
'none'
alpha float

Significance level for (adjusted) confidence intervals.

0.05

Returns:

Type Description
DataFrame

Columns: comparison, diff, se, z, pvalue, pvalue_adj, ci_lower, ci_upper.

Examples:

>>> result = sp.regress("wage ~ C(group) + experience", data=df)
>>> sp.pwcompare(result, data=df, variable="group", adjust="bonferroni")

test

test(result, hypothesis: str) -> Dict[str, float]

Wald test for linear restrictions on coefficients.

Parameters:

Name Type Description Default
result EconometricResults or CausalResult

Fitted model with .params and .std_errors.

required
hypothesis str

Hypothesis specification. Examples: - "x1 = 0" — test if beta_x1 = 0 - "x1 = x2" — test if beta_x1 = beta_x2 - "x1 = x2 = 0" — joint test - "x1 + x2 = 1" — linear restriction

required

Returns:

Type Description
dict

{'statistic': F, 'pvalue': p, 'df': (k, n-K), 'hypothesis': str}

Examples:

>>> result = sp.regress("y ~ x1 + x2 + x3", data=df)
>>> sp.test(result, "x1 = x2")           # beta1 = beta2?
>>> sp.test(result, "x1 = x2 = 0")       # joint: beta1 = beta2 = 0?
>>> sp.test(result, "x1 + x2 = 1")       # beta1 + beta2 = 1?

lincom

lincom(result, expression: str, alpha: float = 0.05) -> Dict[str, float]

Estimate a linear combination of coefficients with inference.

Parameters:

Name Type Description Default
result EconometricResults or CausalResult

Fitted model.

required
expression str

Linear combination. Examples: - "x1 + x2" — beta_x1 + beta_x2 - "x1 - x2" — beta_x1 - beta_x2 - "2*x1 + 3*x2" — 2beta_x1 + 3beta_x2

required
alpha float

Significance level.

0.05

Returns:

Type Description
dict

{'estimate': float, 'se': float, 'z': float, 'pvalue': float, 'ci': (lower, upper), 'expression': str}

Examples:

>>> result = sp.regress("y ~ x1 + x2", data=df)
>>> sp.lincom(result, "x1 + x2")         # beta1 + beta2
>>> sp.lincom(result, "x1 - x2")         # beta1 - beta2

postestimation_contract

postestimation_contract(result: Any, *, data: Optional[DataFrame] = None, include_diagnostics: bool = True) -> Dict[str, Any]

Return the post-estimation actions supported by result.

Parameters:

Name Type Description Default
result object

Fitted StatsPAI result, estimator, or compatible object.

required
data DataFrame

Analysis frame available for data-dependent actions. When supplied, the contract marks margins/predict paths as ready rather than merely method-available.

None
include_diagnostics bool

Include scalar diagnostics from model_info / diagnostics.

True

Returns:

Type Description
dict

Machine-readable contract with available, missing, recommended_next, and optional diagnostics keys.