Panel Dimensions

Use dims when your dataset is a panel rather than a single timeseries.

Examples of useful panel dimensions:

  • geo
  • brand
  • market
  • country

For the input row layout, see Panel Data Layout.

What dims does

dims tells PanelMMM which extra categorical axes exist alongside date.

With no extra dims, the model is indexed by:

  • date
  • channel
  • optionally control

With dims=("geo",), the model is indexed by:

  • date
  • geo
  • channel
  • optionally control

With dims=("geo", "brand"), it is indexed by:

  • date
  • geo
  • brand
  • channel
  • optionally control

What changes inside the model

Setting dims changes the coordinates and parameter shapes used in the PyMC graph.

Quantity No extra dims dims=("geo",)
channel_data ("date", "channel") ("date", "geo", "channel")
target_data ("date",) ("date", "geo")
channel_contribution ("date", "channel") ("date", "geo", "channel")
control_contribution ("date", "control") ("date", "geo", "control")
intercept prior dims by default () ("geo",)

Reserved names

Do not use these names in dims:

  • date
  • channel
  • control
  • fourier_mode

Abacus rejects them because they are reserved for internal coordinates.

dims does not imply automatic pooling

This is the most important modelling point.

By default, dims gives you parameters indexed by the panel coordinates, but not automatic hierarchical shrinkage across those coordinates.

For example:

  • the default intercept prior is Normal(..., dims=dims)
  • transform priors default to (*dims, "channel")
  • control coefficients default to (*dims, "control")

Those defaults create per-slice parameters. If you want hierarchical pooling across geo, brand, or another dimension, you need to encode that in the priors you supply.

Example: independent panel slices

mmm = PanelMMM(
    date_column="date",
    target_column="sales",
    channel_columns=["tv", "search"],
    dims=("geo",),
    adstock=GeometricAdstock(l_max=8),
    saturation=LogisticSaturation(),
)

With this specification, the default priors are geo-indexed, but not hierarchical by default.

Example: explicit hierarchical prior

If you want hierarchical structure, define it in the prior itself.

from pymc_extras.prior import Prior

model_config = {
    "intercept": Prior(
        "Normal",
        mu=0,
        sigma=Prior("HalfNormal", sigma=0.3),
        dims="geo",
    ),
}

You can do the same for transform priors and additive effects.

Mundlak CRE and panel dimensions

use_mundlak_cre=True only makes sense when you have at least one panel dim. Abacus enforces that.

When enabled, Abacus builds extra correlated-random-effects terms from training period means:

  • channel_mundlak_contribution
  • control_mundlak_contribution
  • mundlak_contribution

These terms live on the panel coordinates defined by dims.

Custom HSGP dims

If you use a custom SoftPlusHSGP for time-varying effects, its dims must be compatible with the panel structure.

Examples:

  • no extra dims: ("date",) or ("date", "channel") for media
  • dims=("geo",): ("date", "geo") or ("date", "geo", "channel") for media

See Time-Varying Parameters.

YAML example

data:
  date_column: date

target:
  column: sales
  type: revenue

dimensions:
  panel: [geo, brand]

media:
  channels: [tv, search]
  adstock:
    type: geometric
    l_max: 8
  saturation:
    type: logistic

Your dataset must then contain both geo and brand columns.

Common pitfalls

  • Using reserved names in dims
  • Assuming dims implies automatic partial pooling
  • Enabling use_mundlak_cre with no panel dimensions
  • Forgetting that every date + dims combination must be present in the data

Next steps