apportion#

Shared apportionment of reference-polygon values across an n:m link.

Single implementation of “spread a reference polygon’s values (e.g. a parcel’s improvement value) across the spine entities overlapping it”, following Lochhead et al. (2026, Table 4). Used by both pipeline stages:

  • harmonize: reconcile_attributes() feeds it the in-memory identity overlay;

  • curate: the apportion_curated_values step feeds it the link sidecar persisted by the harmonize overlay (save_link: true), joined to the curated reference entity’s values.

Keeping the two stages on one code path guarantees the apportionment semantics (overlap-area shares, dwelling-linked suppression, primary-only columns, secondary handling) can never drift between them.

Functions#

apportion_reference_values(→ pandas.DataFrame)

Apportion reference values to spine entities over an n:m link.

Module Contents#

openplaces.io.harmonizer.apportion.apportion_reference_values(pairs: pandas.DataFrame, ref_values: pandas.DataFrame, *, spine_id_col: str, ref_id_col: str = 'parcel_id', area_col: str = 'area_intersection_m2', priority: pandas.Series | None = None, dwelling_linked_ids: set | None = None, volume_weight: pandas.Series | None = None) pandas.DataFrame#

Apportion reference values to spine entities over an n:m link.

Column semantics (only columns present in ref_values are produced):

  • improvement_value: multiplied by each pair’s within-reference overlap fraction and summed per spine entity; missing (not 0) on entities whose priority is 'secondary'.

  • n_dwellings: zeroed on 'secondary' entities (an accessory structure contains no dwellings), then fraction-split and summed.

  • year_built: 0 treated as missing, mean over the entity’s linked references (unweighted).

  • land_value: the dominant (largest-overlap) reference’s whole value, kept only on principal entities — priority == 'primary' when priority is given, else entities that are the sole spine entity on their dominant reference — and suppressed for entities affected by the dwelling-linked rule below.

  • address: the dominant reference’s value, unrestricted.

Parameters:
  • pairs (pandas.DataFrame) – One row per (spine entity, reference) link, with columns spine_id_col, ref_id_col, and area_col. Rows with a missing reference id are ignored.

  • ref_values (pandas.DataFrame) – Reference values indexed by ref_id_col. Only columns from APPORTIONED_VALUE_COLUMNS are consumed.

  • spine_id_col (str) – Name of the spine-entity id column in pairs.

  • ref_id_col (str, optional) – Name of the reference id column in pairs (default parcel_id).

  • area_col (str, optional) – Overlap-area column in pairs used for fractions and dominance.

  • priority (pandas.Series, optional) – priority_on_parcel-style role per spine id ('primary' / 'secondary' / 'unknown'). Drives the secondary and principal-only rules above.

  • dwelling_linked_ids (set, optional) – Spine ids with dwelling-point evidence. Within references where at least one linked entity has such evidence, entities without it get a zero share (fractions renormalize over the rest) and their land_value is suppressed (Lochhead et al. 2026, Table 4, Cases 1–2 vs. Case 3).

  • volume_weight (pandas.Series, optional) – Story count per spine id; when given, fractions weight by area × max(n_stories, 1) instead of area alone.

Returns:

Indexed by spine id (only ids appearing in pairs), with one column per apportioned value.

Return type:

pandas.DataFrame