| Title: | Create Persistent Identifiers for Longitudinal Spatial Data |
| Version: | 0.1.0 |
| 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. |
| License: | MIT + file LICENSE |
| URL: | https://github.com/emre-cebeci/spatpersist |
| BugReports: | https://github.com/emre-cebeci/spatpersist/issues |
| Encoding: | UTF-8 |
| Imports: | sf |
| Suggests: | knitr, rmarkdown, testthat (≥ 3.0.0) |
| VignetteBuilder: | knitr |
| Config/testthat/edition: | 3 |
| Config/roxygen2/version: | 8.1.0 |
| NeedsCompilation: | no |
| Packaged: | 2026-08-24 15:38:56 UTC; emrecebeci |
| Author: | Emre Cebeci [aut, cre] |
| Maintainer: | Emre Cebeci <cebeciemre1@gmail.com> |
| Repository: | CRAN |
| Date/Publication: | 2026-09-05 13:50:02 UTC |
Persistent identifiers for longitudinal polygon data
Description
spatpersist links polygon features observed at different times while keeping
four related concepts separate: the persistent identity of a unit, versions
of its geometry, its broader lineage, and its immediate parent following a
structural transition. Matching is based on polygon overlap and is designed
to remain auditable through explicit scores, confidence flags, transition
tables, and validation checks.
Main workflow
Use persist_ids() to assign identifiers to a time-indexed sf
object. Inspect the result with id_transitions() and
id_lineages(), and run validate_ids() before relying on
the identifiers downstream. plot_lineage() provides a compact
visual check of one lineage through time.
Reproducible reruns
A registry written by persist_ids() can be supplied to a later run
so that already-observed units retain their identifiers. Registry matches
are reported in the registry_matched output column. If new spatial evidence
connects multiple prior lineages, they consolidate under the smallest
existing lineage identifier.
Interpretation
A persistent ID represents continuity under the selected overlap rule; it is not a claim that the polygon is geometrically unchanged. Geometry changes receive new version IDs. Splits, merges, births, deaths, and ambiguous candidates remain visible in the audit outputs rather than being silently collapsed. All identifiers are dataset-local, not globally unique: their persistence is scoped to one dataset and its registry chain.
Author(s)
Maintainer: Emre Cebeci cebeciemre1@gmail.com
Authors:
Emre Cebeci cebeciemre1@gmail.com
See Also
vignette("spatpersist-workflow", package = "spatpersist")
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 |
time |
A single character string naming the time column in |
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 |
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 |
time |
A single character string naming the time column in |
threshold |
A number from 0 to 1 giving the minimum overlap required for continuity. |
metric |
The overlap statistic used for matching: |
match_rule |
Candidate selection rule: |
ambiguity_tolerance |
Maximum difference between eligible top scores that is treated as a near tie. |
ambiguity_action |
How near ties should be handled: |
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:
|
geometry_precision |
Optional positive precision scale passed to
|
max_time_gap |
Maximum gap across which identities may continue.
Defaults to |
registry |
Optional prior |
registry_threshold |
Minimum same-time IoU required to recover an
observation from |
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 |
time |
A single character string naming the time column in |
lineage_id |
Optional character vector of lineage IDs to display.
|
show_legend |
Logical; display a transition-type legend. |
node_cex |
Numeric node size. |
... |
Additional arguments passed to |
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 |
time |
A single character string naming the time column in |
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")