Package 'spatpersist'

Title: Create Persistent Identifiers for Longitudinal Spatial Data
Description: Creates dataset-local persistent identifiers for polygon units observed across time. Configurable overlap metrics, thresholds, and one-to-one matching rules identify continuity while separate identifiers track boundary versions and broader lineages through splits, mergers, and replacements. Candidate-link diagnostics, validation checks, registry reconciliation, and lineage summaries keep the resulting decisions inspectable and reproducible.
Authors: Emre Cebeci [aut, cre]
Maintainer: Emre Cebeci <[email protected]>
License: MIT + file LICENSE
Version: 0.1.0
Built: 2026-09-26 23:27:48 UTC
Source: https://github.com/emre-cebeci/spatpersist

Help Index


Create an example longitudinal spatial dataset

Description

Generates synthetic polygon data showing common spatial continuity problems: stable units, boundary changes, renames, and splits.

Usage

example_units()

Value

An sf object containing synthetic polygons.

Examples

data <- example_units()
plot(data["name"])

Summarize persistent spatial identities and lineages

Description

Creates one row per spatial_id with its lineage, parent, observed time span, number of observations and geometry versions, registry recovery count, ambiguity count, and minimum non-missing match confidence.

Usage

id_lineages(data, time)

Arguments

data

A result returned by persist_ids().

time

A single character string naming the time column in data.

Value

A data frame with one row per persistent spatial identity.

Examples

result <- persist_ids(example_units(), time = "year")
id_lineages(result, time = "year")

Inspect spatial transition diagnostics

Description

Retrieves the candidate-link diagnostics created by persist_ids(). The table contains every positive-area overlap considered across successive observed periods, including its overlap statistics, mutual-best and ambiguity flags, candidate status, selection, and confidence.

Usage

id_transitions(x)

Arguments

x

An sf result returned by persist_ids().

Value

A data frame of transition diagnostics.

Examples

result <- persist_ids(example_units(), time = "year")
id_transitions(result)

Create persistent identifiers for longitudinal polygons

Description

Assigns persistent identifiers by comparing polygons in each pair of successive observed time periods. A polygon continues an earlier identity when its selected overlap statistic meets threshold. Candidate links are selected one-to-one, so a persistent identifier cannot occur more than once in the same time period.

Usage

persist_ids(
  data,
  time,
  threshold = 0.75,
  metric = c("share_old", "share_new", "iou"),
  match_rule = c("greedy", "mutual_best"),
  ambiguity_tolerance = 0.05,
  ambiguity_action = c("flag", "new", "error"),
  event_threshold = 0.1,
  lineage_threshold = 0.6,
  version_threshold = 1,
  geometry_action = c("error", "repair"),
  geometry_precision = NULL,
  max_time_gap = Inf,
  registry = NULL,
  registry_threshold = 0.999999
)

Arguments

data

An sf object containing polygon geometries observed over time.

time

A single character string naming the time column in data.

threshold

A number from 0 to 1 giving the minimum overlap required for continuity.

metric

The overlap statistic used for matching: "share_old", "share_new", or "iou".

match_rule

Candidate selection rule: "greedy" considers every eligible link, while "mutual_best" considers only links that are best for both their predecessor and successor.

ambiguity_tolerance

Maximum difference between eligible top scores that is treated as a near tie.

ambiguity_action

How near ties should be handled: "flag" selects deterministically and marks the result, "new" rejects ambiguous links, and "error" stops before assigning IDs.

event_threshold

A number from 0 to 1 giving the minimum share of a predecessor or successor used when detecting splits and mergers.

lineage_threshold

A number from 0 to 1 giving the minimum share of the smaller polygon that must overlap to connect two observations in the same lineage. Accepted identity matches are always connected.

version_threshold

A number from 0 to 1 giving the minimum IoU needed for a continuing identity to retain its current geometry version. The default of 1 creates a new version for any boundary change.

geometry_action

How invalid polygon geometries should be handled: "error" or "repair". Repair uses sf::st_make_valid() and returns the repaired geometries.

geometry_precision

Optional positive precision scale passed to sf::st_set_precision() before spatial operations. Coordinates are rounded as round(x * geometry_precision) / geometry_precision; for example, use 100 for two decimal places. NULL preserves input precision.

max_time_gap

Maximum gap across which identities may continue. Defaults to Inf. Finite values require a numeric, Date, or POSIXt time column; Date gaps use days and POSIXt gaps use seconds.

registry

Optional prior sf result from persist_ids(). Same-time geometries are used to preserve previously issued spatial and geometry-version identifiers across reruns. Existing lineage identifiers are also retained unless new spatial evidence connects multiple registry lineages; the connected component then uses the lexicographically smallest existing lineage identifier.

registry_threshold

Minimum same-time IoU required to recover an observation from registry.

Details

Names and other non-spatial attributes are not used for matching. Unmatched polygons receive new identifiers. Strong spatial links connect related identities in a shared lineage and are used to describe splits, mergers, replacements, and complex reorganizations.

Candidate-link diagnostics are stored with the result and can be retrieved with id_transitions().

Identifiers are dataset-local. Values such as SID000001 and LID000001 are persistent only within one dataset and its registry chain; they are not globally unique across independent projects. Exact same-period coextensive geometries are rejected because geometry-only matching cannot distinguish their identities reproducibly.

Value

The input sf object with identifier and transition columns, including spatial_id, spatial_version_id, lineage_id, parent_id, transition_type, match_score, match_confidence, and match_ambiguous. registry_matched indicates recovered observations.

Examples

data <- example_units()
result <- persist_ids(data, time = "year", threshold = 0.75)
result[, c("year", "name", "spatial_id")]

Plot spatial identity lineages over time

Description

Draws observations on a time-by-identity layout. Solid links are selected identity continuations; dashed links are additional spatial lineage relationships such as split and merger branches.

Usage

plot_lineage(
  data,
  time,
  lineage_id = NULL,
  show_legend = TRUE,
  node_cex = 1.2,
  ...
)

Arguments

data

A result returned by persist_ids().

time

A single character string naming the time column in data.

lineage_id

Optional character vector of lineage IDs to display. NULL displays every lineage.

show_legend

Logical; display a transition-type legend.

node_cex

Numeric node size.

...

Additional arguments passed to graphics::plot.default().

Value

Invisibly, a list containing the plotted nodes and edges data.

Examples

result <- persist_ids(example_units(), time = "year")
plot_lineage(result, time = "year", lineage_id = "LID000004")

Validate persistent spatial identifiers

Description

Checks a result for structural inconsistencies, including missing output values, duplicate identities within a time period, identities assigned to multiple lineages, invalid geometry-version sequences, invalid transition labels, invalid match scores, and broken parent or continuation links.

Usage

validate_ids(data, time)

Arguments

data

A data frame or sf object containing spatial ID output.

time

A single character string naming the time column in data.

Value

A data frame describing validation issues. A result with zero rows passed all implemented checks.

Examples

result <- persist_ids(example_units(), time = "year")
validate_ids(result, time = "year")