Comparison Outputs
ScenarioPlanner returns structured planning tables rather than a single
optimiser object.
This page explains the output objects and the meaning of each table.
Import these objects from abacus.scenarios for new statistical scenario
code. abacus.scenario_planner remains a compatibility namespace for existing
statistical imports and legacy dashboard app-layer paths.
Output objects
| Object | Produced by | Tables |
|---|---|---|
ScenarioResult |
planner.evaluate(spec) |
totals, channels, contributions_over_time, allocation, metadata |
ScenarioComparison |
planner.compare(specs) |
totals, channels, contributions_over_time, allocations, metadata |
ScenarioComparison is a row-wise concatenation of the individual scenario
results, with scenario identifiers added to every table.
totals
totals has one row per scenario.
It includes:
scenario_idscenario_namescenario_typetotal_spendcontribution_meancontribution_mediancontribution_hdi_94_lowercontribution_hdi_94_upperefficiency_metricefficiency_meanefficiency_medianefficiency_hdi_94_lowerefficiency_hdi_94_upper
efficiency_metric is ROAS for revenue targets and CPA for conversion
targets.
channels
channels has one row per (scenario, channel).
It includes:
- scenario identifiers
channelspendspend_sharespend_per_period- contribution summary columns
- contribution-per-period columns
- efficiency summary columns
efficiency_metric
The planner aggregates non-channel panel dims before it builds this table. For
example, a (geo, channel) model still returns one row per channel here.
contributions_over_time
contributions_over_time has one row per (scenario, date, channel).
It includes:
- scenario identifiers
datechannelcontribution_meancontribution_mediancontribution_hdi_94_lowercontribution_hdi_94_upper
Like channels, this table aggregates non-channel panel dims before
summarising.
allocations
allocations keeps the original allocation grain.
It includes:
- scenario identifiers
- the allocation dims, such as
channel,geo, orbrand allocationrealized_spend
For current scenarios, allocation is the summed historical spend over the
reference window. For simulated scenarios, allocation is the requested total
horizon allocation and realized_spend is the realised spend from the response
simulation.
metadata
metadata is the audit table for each scenario.
Shared fields include:
scenario_idscenario_namescenario_typestart_dateend_dateevaluated_start_dateevaluated_end_datenum_periodstarget_typeefficiency_metric
Additional fields depend on scenario type.
Current scenario metadata
Current scenarios add:
reference_window_dates
Manual scenario metadata
Manual scenarios add:
requested_total_budgettotal_budgetreference_window_datesbudget_unit
Fixed-budget optimised metadata
Optimised scenarios add:
requested_total_budgettotal_budgetoptimization_successoptimization_statusoptimization_messageoptimization_objective_valuereference_window_datesbudget_unit
Requested versus evaluated windows
The metadata table is the best place to check whether the evaluated window matches the requested window.
When include_carryover=True, the evaluated end date can be later than the
requested end_date.
Example inspection
to_store_payload()
ScenarioComparison.to_store_payload() converts the comparison tables into a
JSON-friendly dict:
The payload contains a scalar contract_version and record lists for
totals, channels, contributions_over_time, allocations, and
metadata. The current contract value is exported as
SCENARIO_CONTRACT_VERSION from abacus.scenarios, so downstream clients can
check whether they understand the result shape before rendering or importing
it.
The deprecated experimental abacus-dashboard application consumed this
payload format. The versioned contract remains available to machine consumers:
Abacus owns the statistical result shape; clients own rendering and interaction.
Retained recipe artefacts
run_scenario_recipe(...) and evaluate_scenario_recipe(...) persist the
comparison as an immutable bundle:
| File | Purpose |
|---|---|
scenario_recipe.resolved.yaml |
versioned request after validation |
scenario_validation.json |
scenario IDs, estimator, fitted-unit scope, estimand, and pass state |
estimator_manifest.yaml |
fitted estimator contract copied with the scenario evidence |
scenario_totals.csv |
total spend, contribution, efficiency, and uncertainty by scenario |
scenario_channels.csv |
channel summaries and uncertainty |
scenario_contributions_over_time.csv |
date-channel contribution summaries and uncertainty |
scenario_allocations.csv |
requested allocation and realised spend at the original allocation grain |
scenario_metadata.csv |
scenario semantics, dates, history policy, scale, and estimand |
scenario_payload.json |
versioned five-table payload for machine consumers |
scenario_artifact_manifest.json |
source run ID, file sizes, and SHA-256 checksums |
The target directory must not exist before evaluation. Abacus validates the comparison before it creates the directory and never overwrites an earlier bundle.
Common pitfalls
- Reading
channelsas if it retained non-channel panel dims - Ignoring
metadatawhen carryover is enabled - Comparing requested allocation with realised spend without checking the
allocationstable