Methods for comparing two layers of spatial categorical raster data

Author

Jakub Nowosad

Published

Last Updated: May, 2024

This document shows a set of examples related to the article “Comparing spatial patterns in raster data using R”. The examples are focused on comparing two layers of spatial categorical raster data, and are divided into three groups: raster outcome, single value outcome, and multiple value outcome.

The examples in this document use two raster layers representing the Corine Land Cover (CLC) data (European Environment Agency and European Environment Agency 2019) for Tartu, Estonia, for the years 2000 and 2018, and Poznań, Poland for 2018. The terra package (Hijmans 2024) is used for raster data manipulation.

The calculation time for each example is estimated and displayed at the end of each code chunk.

library(terra)
clc2000_tartu = rast("data/clc2000_tartu.tif")
clc2018_tartu = rast("data/clc2018_tartu.tif")
clc2018_poznan = rast("data/clc2018_poznan.tif")
plot(clc2000_tartu, main = "Tartu (2000)")
plot(clc2018_tartu, main = "Tartu (2018)")
plot(clc2018_poznan, main = "Poznań (2018)")

Time for the above code chunk to run: 5.68 seconds

1 Raster outcome

1.1 Non-spatial context

1.1.1 Non-disjoint areas

1.1.1.1 The binary difference between two rasters

clc_diff = clc2018_tartu != clc2000_tartu
plot(clc_diff)

Time for the above code chunk to run: 0.17 seconds

1.2 Spatial context

1.2.1 Non-disjoint areas

1.2.1.1 The difference between a focal measure of two rasters (e.g., selected landscape metric)

This example uses the landscapemetrics package (Hesselbarth et al. 2019).

library(landscapemetrics)
window = matrix(1, nrow = 5, ncol = 5)
clc2000_tartu_relmutinf_mw = window_lsm(clc2000_tartu, window = window, what = "lsm_l_relmutinf")
clc2018_tartu_relmutinf_mw = window_lsm(clc2018_tartu, window = window, what = "lsm_l_relmutinf")
clc2018_tartu_relmutinf_diff = abs(clc2018_tartu_relmutinf_mw[[1]][[1]] - clc2000_tartu_relmutinf_mw[[1]][[1]])
plot(clc2018_tartu_relmutinf_diff)

Time for the above code chunk to run: 54.56 seconds

1.2.1.2 Cross-entropy loss function

This example uses the spatialEco package (Evans and Murphy 2023).

library(spatialEco)
clc_ce = raster.change(clc2000_tartu, clc2018_tartu, s = 5, 
                       stat = "cross-entropy")
plot(clc_ce)

Time for the above code chunk to run: 144.55 seconds

2 Single value outcome

2.1 Non-spatial context

2.1.1 Non-disjoint areas

2.1.1.1 The proportion of changed pixels

clc_diff = clc2018_tartu != clc2000_tartu
changed_pixels = freq(clc_diff)$count[2]
total_pixels = ncell(clc_diff)
proportion_changed = changed_pixels / total_pixels
proportion_changed
[1] 0.05443125

Time for the above code chunk to run: 0.05 seconds

2.1.1.2 The overall comparison (Pontius 2002)

clc2000_tartu_freq = freq(clc2000_tartu)
clc2018_tartu_freq = freq(clc2018_tartu)
freq = merge(clc2000_tartu_freq, clc2018_tartu_freq, by = "value", all = TRUE)
freq[is.na(freq)] = 0
freq$diff = abs(freq$count.x - freq$count.y)
sum_diff = sum(freq$diff)
total_pixels = ncell(clc_diff)
1 - sum_diff / total_pixels
[1] 0.9716375

Time for the above code chunk to run: 0.32 seconds

2.1.1.3 Statistics of the differences between rasters’ values

Overall difference metrics from the diffeR package (Pontius Jr. and Santacruz 2023).

library(diffeR)
clc_ct = crosstabm(clc2000_tartu, clc2018_tartu)
overallAllocD(clc_ct)
[1] 6440
overallDiff(clc_ct)
[1] 8709
overallExchangeD(clc_ct)
[1] 5280
overallQtyD(clc_ct)
[1] 2269
overallShiftD(clc_ct)
[1] 1160

Time for the above code chunk to run: 4.52 seconds

2.1.2 Disjoint areas

2.1.2.1 Comparison of the values of a non-spatial landscape metric

This example uses the landscapemetrics package (Hesselbarth et al. 2019).

library(landscapemetrics)
clc2018_tartu_shdi = lsm_l_shdi(clc2018_tartu)
clc2018_poznan_shdi = lsm_l_shdi(clc2018_poznan)
abs(clc2018_poznan_shdi$value - clc2018_tartu_shdi$value)
[1] 0.02981541

Time for the above code chunk to run: 0.21 seconds

2.2 Spatial context

2.2.1 Non-disjoint areas

2.2.1.1 Spatial association between regionalizations using V-measure

This example uses the sabre package (J. Nowosad and Stepinski 2018).

library(sabre)
clc_sabre = vmeasure_calc(clc2000_tartu, clc2018_tartu)
plot(clc_sabre$map1)

plot(clc_sabre$map2)

Time for the above code chunk to run: 5.73 seconds

2.2.2 Disjoint areas

2.2.2.1 Comparison of the values of a landscape metric

This example uses the landscapemetrics package (Hesselbarth et al. 2019).

library(landscapemetrics)
clc2018_tartu_ed = lsm_l_ed(clc2018_tartu)
clc2018_poznan_ed = lsm_l_ed(clc2018_poznan)
abs(clc2018_poznan_ed$value - clc2018_tartu_ed$value)
[1] 5.63159

Time for the above code chunk to run: 0.17 seconds

2.2.2.2 Comparison of the values of Zhao’s entropy for landscape mosaics (Zhao and Zhang 2019)

This example uses the bespatial package (Jakub Nowosad 2024).

library(bespatial)
clc2018_tartu_bes = bes_m_zhao(clc2018_tartu)
clc2018_poznan_bes = bes_m_zhao(clc2018_poznan)
abs(clc2018_poznan_bes$value - clc2018_tartu_bes$value)
[1] 0.00207152

Time for the above code chunk to run: 0.79 seconds

2.2.2.3 Dissimilarity of a spatial signature between two rasters (Jasiewicz and Stepinski 2013)

This example uses the motif package (Jakub Nowosad 2021).

library(motif)
library(philentropy)
clc2018_tartu_sign = lsp_signature(clc2018_tartu, type = "cove", threshold = 1)
clc2018_poznan_sign = lsp_signature(clc2018_poznan, type = "cove", threshold = 1)
jensen_shannon(clc2018_tartu_sign$signature[[1]],
               clc2018_poznan_sign$signature[[1]], 
               testNA = FALSE, unit = "log2")
[1] 0.08261638

Time for the above code chunk to run: 0.43 seconds

3 Multiple value outcome

table(values(clc2000_tartu), values(clc2018_tartu))
   
        1     2     3     4     6     7
  1  4821   357     2    10     0     0
  2  1342 67915   684   389     0     0
  3    59   415 33670  2896     9    22
  4   122   638  1435  7040   229    24
  6     0     3    13    20  2177    37
  7     0     0     0     0     3  1995

Time for the above code chunk to run: 0.08 seconds

References

European Environment Agency, and European Environment Agency. 2019. CORINE Land Cover 2018 (Raster 100 m), Europe, 6-Yearly - Version 2020_20u1, May 2020.” European Environment Agency. https://doi.org/10.2909/960998C1-1870-4E82-8051-6485205EBBAC.
Evans, Jeffrey S., and Melanie A. Murphy. 2023. spatialEco. Manual.
Hesselbarth, Maximilian H. K., Marco Sciaini, Kimberly A. With, Kerstin Wiegand, and Jakub Nowosad. 2019. Landscapemetrics : An Open-Source R Tool to Calculate Landscape Metrics.” Ecography 42 (10): 1648–57. https://doi.org/gf4n9j.
Hijmans, Robert J. 2024. Terra: Spatial Data Analysis. Manual.
Jasiewicz, Jaroslaw, and Tomasz F. Stepinski. 2013. “Example-Based Retrieval of Alike Land-Cover Scenes From NLCD2006 Database.” IEEE Geoscience and Remote Sensing Letters 10 (1): 155–59. https://doi.org/gjnqqx.
Nowosad, Jakub. 2021. “Motif: An Open-Source R Tool for Pattern-Based Spatial Analysis.” Landscape Ecology 36: 26–43. https://doi.org/10.1007/s10980-020-01135-0.
———. 2024. Bespatial: Boltzmann Entropy for Spatial Data. Manual.
Nowosad, J., and T. F. Stepinski. 2018. “Spatial Association Between Regionalizations Using the Information-Theoretical V -Measure.” International Journal of Geographical Information Science 32 (12): 2386–2401. https://doi.org/gf283f.
Pontius Jr., Robert Gilmore, and Ali Santacruz. 2023. diffeR: Metrics of Difference for Comparing Pairs of Maps or Pairs of Variables. Manual.
Pontius, R Gil. 2002. “Statistical Methods to Partition Effects of Quantity and Location During Comparison of Categorical Maps at Multiple Resolutions.” Photogrammetric Engineering.
Zhao, Y., and X. C. Zhang. 2019. “Calculating Spatial Configurational Entropy of a Landscape Mosaic Based on the Wasserstein Metric.” Landscape Ecology 34 (8): 1849–58. https://doi.org/gkb47d.

Reuse