Skip to content

Weighted consensus and categorical breakpoint detection for change confidence #9

@NewGraphEnvironment

Description

@NewGraphEnvironment

Context

dft_rast_consensus() (#8) computes per-pixel mode across classified rasters. This works well for filtering single-year misclassification noise, but has a fundamental limitation: it can't distinguish noise from real change.

The problem

A pixel that transitions Trees → Rangeland in 2022 looks like this across a 2021-2023 window:

Year Class
2021 Trees
2022 Rangeland
2023 Rangeland

Mode = Trees (2/3 if tied, or Rangeland 2/3 depending on direction). The consensus either misses the real change or requires the post-change class to dominate the window before it registers.

A 3-year window needs 2+ years of the new class. A 5-year window needs 3+. Real change is slow to detect; noise filtering improves.

Possible approaches

Weighted mode

Give recent years more weight (e.g. 2023 counts 2x). Faster to detect real change while still smoothing older noise. Simple extension of current function.

Breakpoint / trajectory detection

Detect when a pixel changed, not just what it became. Trees/Trees/Trees/Rangeland/Rangeland = real change at year 4 with high confidence. Trees/Rangeland/Trees/Rangeland/Trees = noise.

Established algorithms for this exist but work on continuous spectral values, not categorical classes:

  • BFAST (Breaks For Additive Season and Trend) — decomposes pixel time series into trend + seasonal + remainder, detects breakpoints. R package bfast. Designed for deforestation monitoring.
  • LandTrendr — fits piecewise linear segments to spectral history. Available in GEE + R.

Both require raw spectral bands (NDVI, NBR), not pre-classified maps. Using them in drift would mean a fundamentally different pipeline: fetch raw bands → build per-pixel time series → detect breakpoints → classify segments.

Categorical breakpoint detection

A simpler approach that works with classified inputs: scan each pixel's class sequence for sustained transitions. If a pixel holds class A for N consecutive years then switches to class B for M consecutive years, that's a real change with confidence proportional to min(N, M). This doesn't exist as a package and could be drift's niche — breakpoint detection for categorical time series.

Recommendation

Start with weighted mode as a parameter on dft_rast_consensus(). File categorical breakpoint detection as a separate future exploration if the weighted approach isn't sufficient.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions