Temporal networks

Build snapshots from the dates in a processed OD table, with a shared node order. For downloaded data, provide the acquisition manifest from get_acquisition_manifest(). The examples show how source coverage changes the mean.

  • snapshot() builds a network for one observed day.

  • sum_network() sums selected observed days.

  • mean_per_observed_day() divides by the number of selected observed days, including genuinely observed days with no retained flows.

  • coverage identifies observed, missing and unresolved dates.

  • Snapshot comparison methods use the same measures as Flow measures and comparisons.

Build temporal networks

pyspainmobility.network.temporal.build_temporal_network(data: str | Path | DataFrame | DataFrame | LazyFrame, *, spec: NetworkSpec | None = None, time_column: str = 'date', requested_dates: Sequence[object] | None = None, observed_dates: Sequence[object] | None = None, acquisition_manifest: DataFrame | DataFrame | None = None, manifest_date_column: str = 'date', manifest_status_column: str = 'status', node_ids: Sequence[object] | None = None, node_index: NodeIndex | None = None, max_cached_snapshots: int | None = 32, failed_data_policy: Literal['error', 'exclude'] = 'error') → TemporalMobilityNetwork[source]

Build daily networks with a shared node order and explicit source coverage.

Parameters:
  • data (str, pathlib.Path, pandas.DataFrame, polars.DataFrame or polars.LazyFrame) – Processed OD rows or a Parquet file/dataset directory.

  • spec (NetworkSpec, optional) – Weight column and self-loop policy, as in build_network().

  • time_column (str) – Column identifying the observation date. Default is 'date'.

  • requested_dates (sequence, optional) – Dates to analyse, including any requested days that may be missing. Must contain at least one date when provided.

  • observed_dates (sequence, optional) – Dates of successfully observed source days, including known empty days. Use either this argument or acquisition_manifest.

  • acquisition_manifest (pandas.DataFrame or polars.DataFrame, optional) – Source-day record from Mobility.get_acquisition_manifest(). Failed source days are excluded from observed coverage.

  • manifest_date_column (str) – Manifest columns. Defaults are 'date' and 'status'.

  • manifest_status_column (str) – Manifest columns. Defaults are 'date' and 'status'.

  • node_ids (sequence, optional) – Complete, ordered node universe, including isolates.

  • node_index (NodeIndex, optional) – Shared node order and zoning identity; cannot be combined with node_ids.

  • max_cached_snapshots (int or None) – Maximum snapshots retained in memory. Default is 32; 0 disables caching, and None leaves the cache unbounded.

  • failed_data_policy ({'error', 'exclude'}) – Raise if OD rows belong to failed source days, or explicitly remove all such rows. Default is 'error'.

Returns:

Daily snapshots, sums and means over observed days, with source coverage in coverage. Snapshot matrices are built only when requested.

Return type:

TemporalMobilityNetwork

Notes

observed_dates is deliberately separate from OD rows. Pass the dates of source files successfully obtained/parsed to correctly represent an observed day with zero OD rows. Prefer acquisition_manifest from Mobility.get_acquisition_manifest(): it also records failed and empty source files before OD filtering. If both are omitted, source coverage is inferred from data rows and requested-but-empty dates stay unresolved.

data may be a Hive-partitioned Parquet directory such as date=2024-01-01/part-0.parquet. The partition column is available as time_column and date filters retain Polars partition pruning. By default at most 32 snapshot matrices are retained; pass None for an unbounded cache or 0 to disable snapshot caching.

If a source manifest marks a day as failed but the OD table still contains its rows, the default failed_data_policy='error' stops the pipeline: a partial day must never enter an observed-day average. Pass 'exclude' to deliberately remove every row for such failed dates.

Examples

>>> import polars as pl
>>> from pyspainmobility import build_temporal_network
>>> od = pl.DataFrame({
...     "date": ["2024-01-01", "2024-01-03"],
...     "id_origin": ["A", "A"], "id_destination": ["B", "B"],
...     "n_trips": [3.0, 5.0],
... })
>>> temporal = build_temporal_network(
...     od, observed_dates=["2024-01-01", "2024-01-03"],
... )
>>> temporal.snapshot("2024-01-01").total_weight
3.0
>>> temporal.mean_per_observed_day().total_weight
4.0

Snapshots and aggregates

Create this result with build_temporal_network().

class pyspainmobility.network.temporal.TemporalMobilityNetwork(_source: LazyFrame, time_column: str, spec: NetworkSpec, node_ids: ndarray, coverage: TemporalCoverage, max_cached_snapshots: int | None = 32, _cache: OrderedDict[str, ~pyspainmobility.network.model.SparseMobilityNetwork]=<factory>, node_index: NodeIndex | None = None)[source]

Lazy snapshots that share one immutable node index.

Snapshot matrices are constructed only when requested. An LRU cache bounds retained CSR matrices while every snapshot uses the same node_ids, so entries at the same matrix coordinates refer to the same zones.

property number_of_observed_days: int

Days known observed in the source, including known empty days.

snapshot(when: object) → SparseMobilityNetwork[source]

Return the network for one observed source day.

Parameters:

when (str or date-like) – Observed date, for example '2024-01-01'. A missing source day raises.

Returns:

Daily network with the temporal result’s shared node index. Known empty observed days return a zero-flow matrix retaining all nodes.

Return type:

SparseMobilityNetwork

clear_cache() → None[source]

Release all cached snapshot matrices without changing the source.

snapshots(include_empty: bool = False) → Iterator[Tuple[str, SparseMobilityNetwork]][source]

Yield snapshots in date order, building each one only on demand.

sum_network(dates: Sequence[object] | None = None) → SparseMobilityNetwork[source]

Sum flows across selected observed source dates.

Parameters:

dates (sequence, optional) – Observed days to sum. None selects all observed source days.

Returns:

Summed flows with the shared node index and selected dates in the audit.

Return type:

SparseMobilityNetwork

mean_per_observed_day(dates: Sequence[object] | None = None) → SparseMobilityNetwork[source]

Average flows over selected observed source dates.

Known empty observed dates remain in the denominator. A requested date that is missing or failed in the source manifest raises instead of being converted to a zero-flow day.

Parameters:

dates (sequence, optional) – Observed days to average. None selects all observed source days.

Returns:

Summed flows divided by the number of selected observed days, with that denominator and the selected dates recorded in the audit.

Return type:

SparseMobilityNetwork

snapshot_strengths(when: object) → DataFrame[source]

Return in/out weighted strength for every node on one observed day.

compare_snapshots(left: object, right: object) → NetworkComparison[source]

Compare two observed dates with a shared node-index contract.

snapshot_edge_changes(left: object, right: object) → DataFrame[source]

Return the sparse union of directed-edge changes between two dates.

destination_stability(left: object, right: object) → DataFrame[source]

Return per-origin destination-profile similarity between two dates.

audit() → Dict[str, object][source]

Return temporal coverage and cache status.

Source coverage

class pyspainmobility.network.temporal.TemporalCoverage(requested_dates: Tuple[str, ...], source_dates: Tuple[str, ...], data_dates: Tuple[str, ...], source_manifest_provided: bool, excluded_data_dates: Tuple[str, ...] = (), excluded_data_weight: float = 0.0, excluded_invalid_row_count: int = 0)[source]

Distinguish requested, source-observed, and data-bearing dates.

source_dates comes from a caller-provided source manifest when one is available: for example, the list of downloaded MITMA files that were successfully parsed. It can therefore contain a date with an empty OD file. Without such a manifest it is inferred from OD rows and empty observed days cannot be distinguished from unavailable source days.

property missing_source_dates: Tuple[str, ...]

Requested dates known to be absent from the source manifest.

property empty_observed_dates: Tuple[str, ...]

Observed source dates for which the OD table has no rows.

property unresolved_requested_dates: Tuple[str, ...]

Requested dates whose source availability is unknown.

audit() → Dict[str, object][source]

Return JSON-friendly coverage counts and explicit date categories.