add_secondary_demand
site.SiteProblem.add_secondary_demand(
demand_df,
demand_col,
location_id_col,
label,
skip_cols=None,
also_weight_matrices=None,
)Register an additional demand scenario (e.g. projected future demand alongside a primary current-demand dataset).
Unlike add_demand(), a secondary demand scenario never drives the optimisation objective – the primary demand set via add_demand() (or the equal-demand fallback) always drives site selection and search/pruning. Instead, each registered secondary demand scenario contributes its own weighted_average__<label> and proportion_within_coverage_threshold__<label> metric columns – the two metrics that actually change with demand – into every solution solve() produces, so it can be used directly in plots, Metric(column=...), ranking (sort_by= "weighted_average__future_demand" post-hoc, or solve(rank_on="weighted_average__future_demand") to search on it directly), or blended into the optimisation objective via weights={"future_demand": ...}.
By default a secondary demand scenario only re-weights the primary travel matrix. Pass also_weight_matrices to additionally compute weighted_average__<travel_label>__<label> / proportion_within_coverage_threshold__<travel_label>__<label> against one or more registered secondary travel matrices – this is opt-in because the combination of secondary travel and secondary demand matrices grows the output multiplicatively.
You may call this method multiple times with different labels to register as many demand scenarios as needed. Each one adds approximately the cost of one extra weighted-average/coverage pass over the primary matrix (plus one per named also_weight_matrices entry), so solve() time scales close to linearly with the number of secondary demand scenarios registered.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| demand_df | pandas.DataFrame or geopandas.GeoDataFrame or str | The dataset containing demand for this scenario, or a local or web path to its location. | required |
| demand_col | str | The name of the column in demand_df representing the quantity of demand for this scenario. |
required |
| location_id_col | str | The name of the column in demand_df used as a unique identifier for demand locations (should correspond to IDs in the primary demand data). |
required |
| label | str | A unique label identifying this demand scenario, used to suffix every metric column it produces (e.g. label="future_demand" -> weighted_average__future_demand). Must be non-empty, must not contain "__", and must not already be registered as either a secondary demand scenario or a secondary travel matrix (suffix labels are shared between the two). |
required |
| skip_cols | list of str | A list of column names to ignore during data loading. | None |
| also_weight_matrices | list of str | Labels of registered secondary travel matrices (via add_secondary_travel_matrix()) to also weight by this demand scenario, producing <metric>__<travel_label>__<label> columns. Order of registration does not matter – membership is checked when solve() builds the aligned frames. |
None |
Returns
| Name | Type | Description |
|---|---|---|
| None |
Raises
| Name | Type | Description |
|---|---|---|
| ValueError | If label is empty, contains "__", or has already been registered (as a secondary demand scenario or secondary travel matrix). |
|
| KeyError | If demand_col or location_id_col is missing from the provided dataframe. |
Notes
Secondary demand scenarios must be complete: every demand location present in the primary demand/travel data must have a non-missing value. This is validated when solve() builds the aligned per-solution frames (not here, since the primary demand/travel matrix may not yet be registered).