Summary and Export

mmm.summary is the retained tabular summary surface for fitted PanelMMM models.

It is backed by MMMSummaryFactory and returns pandas or polars DataFrames that you can export with normal DataFrame methods.

For predictive diagnostics and JSON-ready reports, see Diagnostics.

Use mmm.summary

The simplest path is the bound summary factory on the fitted model:

posterior_df = mmm.summary.posterior_predictive()
contributions_df = mmm.summary.contributions(component="channel")
roas_df = mmm.summary.roas(frequency="monthly")

mmm.summary already has access to:

  • mmm.data
  • the fitted PanelMMM
  • the default summary settings

Construct MMMSummaryFactory manually

If you want custom defaults, build the factory yourself:

from abacus.mmm.summary import MMMSummaryFactory

summary = MMMSummaryFactory(
    mmm.data,
    model=mmm,
    hdi_probs=(0.80, 0.94),
    output_format="polars",
)

This is useful when you want one summary object with consistent HDI and output settings across multiple tables.

Common summary methods

Method What it returns
posterior_predictive() Posterior predictive summaries aligned to the wrapped target data
contributions() Tidy contribution summaries by component type
mean_contributions_over_time() Wide decomposition table
roas() / cost_per_target() / efficiency() Efficiency summaries
channel_spend() Raw spend table
saturation_curves() / adstock_curves() Transformation-curve summaries
total_contribution() Component-level totals
change_over_time() Period-on-period percentage change in channel contributions

Choose output format

MMMSummaryFactory supports:

  • output_format="pandas"
  • output_format="polars"

Example:

summary = MMMSummaryFactory(mmm.data, model=mmm, output_format="polars")
roas_df = summary.roas()

If you request polars without Polars installed, Abacus raises an ImportError.

Configure HDI probabilities

Pass HDI probabilities as numbers strictly between 0 and 1:

posterior_df = mmm.summary.posterior_predictive(hdi_probs=[0.80, 0.94])

Do not pass percentages such as 80 or 94.

Summary tables include interval columns named from those probabilities. For example, hdi_probs=[0.94] produces columns such as:

  • abs_error_94_lower
  • abs_error_94_upper

These columns are the current HDI bound columns used by the retained summary surface.

Aggregate over time

Many summary methods accept frequency with one of these values:

  • original
  • weekly
  • monthly
  • quarterly
  • yearly
  • all_time

Example:

monthly = mmm.summary.posterior_predictive(frequency="monthly")
quarterly_roas = mmm.summary.roas(frequency="quarterly")

all_time removes the date dimension. That is useful for fully aggregated tables, but date-dependent summaries still need a date axis.

Do not use all_time with:

  • mean_contributions_over_time()
  • change_over_time()

Export tables

Abacus does not add a separate export wrapper on top of the returned DataFrames. Use the normal DataFrame methods from your selected backend:

posterior_df = mmm.summary.posterior_predictive()
posterior_df.to_csv("posterior_predictive.csv", index=False)

With Polars:

summary = MMMSummaryFactory(mmm.data, model=mmm, output_format="polars")
roas_df = summary.roas()
roas_df.write_csv("roas.csv")

Export diagnostic reports

Diagnostic report objects expose to_dict() for JSON-ready export:

import json

report = mmm.diagnostics.predictive_report()
with open("predictive_report.json", "w", encoding="utf-8") as handle:
    json.dump(report.to_dict(), handle, indent=2)

Common pitfalls

  • Expecting a dedicated file-export API on mmm.summary
  • Passing 94 instead of 0.94 in hdi_probs
  • Using saturation_curves() or adstock_curves() from a manual factory without model=mmm
  • Using all_time on summaries that require a date dimension