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.
spatpersist creates persistent identifiers for polygon units observed over
time. It is designed for datasets in which names, labels, and boundaries may
change and reliable longitudinal IDs do not already exist.
Identity is determined from configurable spatial continuity rules. Names and other descriptive attributes are preserved in the result but are not used for matching.
spatpersistis under active development. Review transition diagnostics and validation results before using generated IDs in analysis.
Install the development version from GitHub:
# install.packages("remotes")
remotes::install_github("emre-cebeci/spatpersist")
library(spatpersist)
polygons <- example_units()
result <- persist_ids(
polygons,
time = "year",
threshold = 0.75,
metric = "share_old"
)
sf::st_drop_geometry(result)[
, c(
"year",
"name",
"spatial_id",
"spatial_version_id",
"lineage_id",
"parent_id",
"transition_type"
)
]
The result remains an sf object in its original row order.
| Column | Meaning |
|---|---|
spatial_id |
One continuing spatial identity. It occurs at most once per time period. |
spatial_version_id |
A consecutive boundary spell within a spatial_id. |
lineage_id |
A broader family connecting related identities through splits, mergers, and replacements. |
parent_id |
The strongest predecessor when a related observation receives a new identity. |
transition_type |
initial, continuation, new, split, merger, replacement, or complex. |
Selected links also receive match_score, match_confidence, and
match_ambiguous. Registry recovery is recorded in registry_matched.
Identifiers are dataset-local, not globally unique. Independent projects can
both contain values such as SID000001; persistence is guaranteed only within
one dataset and its registry chain. Add a project-specific key when combining
outputs from unrelated datasets.
The core identity rule is controlled by:
metric: "share_old", "share_new", or "iou";threshold: minimum accepted value of that metric;match_rule: greedy one-to-one matching or stricter mutual-best matching;ambiguity_tolerance: the score difference treated as a near tie;ambiguity_action: flag, reject, or stop on ambiguous candidates.For example, this rejects near ties instead of selecting one deterministically:
conservative <- persist_ids(
polygons,
time = "year",
metric = "iou",
threshold = 0.75,
match_rule = "mutual_best",
ambiguity_action = "new"
)
event_threshold, lineage_threshold, and version_threshold separately
control event detection, lineage links, and geometry-version changes.
Every positive-area overlap considered by the matching engine is available as a regular data frame:
transitions <- id_transitions(result)
lineages <- id_lineages(result, time = "year")
issues <- validate_ids(result, time = "year")
nrow(issues) # zero means all implemented checks passed
Diagnostics distinguish spatial eligibility, rule eligibility, ambiguity, mutual-best status, selection, confidence, and lineage membership.
plot_lineage(
result,
time = "year",
lineage_id = "LID000004"
)
Solid edges are selected identity continuations. Dashed edges are additional lineage relationships, such as branches created by a split or merger.
A previous result can be supplied as an optional registry. Matching same-time geometries retain their issued IDs, while new identities are allocated above the registry's existing range.
updated_result <- persist_ids(
updated_polygons,
time = "year",
registry = result
)
Conflicting registry identity or geometry-version evidence stops
reconciliation rather than silently renumbering identities. Lineages are
different: if new spatial evidence connects observations anchored to multiple
registry lineages, the complete connected component is consolidated under the
lexicographically smallest existing lineage_id.
sf object containing only POLYGON or MULTIPOLYGON geometries.Invalid polygons can be repaired explicitly with
geometry_action = "repair". Optional geometry precision and maximum time-gap
controls are also available.
max_time_gap prevents a
link.parent_id cannot encode every predecessor in a merger; use
id_transitions() for complete many-to-many evidence.inst/benchmarks; performance still depends strongly on polygon complexity
and the number of candidate intersections.See vignette("spatpersist-workflow") for a complete walkthrough.
Bug reports and contributions are welcome. Please use only synthetic or public data in issues, examples, and pull requests; do not upload confidential or restricted datasets. See CONTRIBUTING.md for the development and reporting workflow.