ndvi_diff = ndvi2023_tartu - ndvi2018_tartu
plot(ndvi_diff)Time for the above code chunk to run: 0.75 seconds
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 continuous 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 NDVI values derived from Sentinel-2 images (“Sentinel-2 MSI Level-2A BOA Reflectance” 2022) for early summer of 2018 and 2023 in the area of Tartu, Estonia, and Poznań, Poland for 2023. 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)
ndvi2018_tartu = rast("data/ndvi2018_tartu.tif")
ndvi2023_tartu = rast("data/ndvi2023_tartu.tif")
ndvi2023_poznan = rast("data/ndvi2023_poznan.tif")
plot(ndvi2018_tartu, main = "Tartu (2018)")
plot(ndvi2023_tartu, main = "Tartu (2023)")
plot(ndvi2023_poznan, main = "Poznań (2023)")Time for the above code chunk to run: 9.18 seconds
ndvi_diff = ndvi2023_tartu - ndvi2018_tartu
plot(ndvi_diff)Time for the above code chunk to run: 0.75 seconds
ndvi_cor = focalPairs(c(ndvi2023_tartu, ndvi2018_tartu), w = 5,
fun = "pearson", na.rm = TRUE)
plot(ndvi_cor)Time for the above code chunk to run: 3.8 seconds
This example uses the geodiv package (Smith et al. 2023).
# 'sa': average surface roughness
library(geodiv)
window = matrix(1, nrow = 5, ncol = 5)
ndvi2018_tartu_sa_mw = focal_metrics(ndvi2018_tartu, window = window,
metric = "sa", progress = FALSE)
ndvi2023_tartu_sa_mw = focal_metrics(ndvi2023_tartu, window = window,
metric = "sa", progress = FALSE)
ndvi_diff_sa_mw = ndvi2023_tartu_sa_mw$sa - ndvi2018_tartu_sa_mw$sa
plot(ndvi_diff_sa_mw)Time for the above code chunk to run: 26.84 seconds
This example uses the GLCMTextures package (Ilich 2020).
library(GLCMTextures)
ndvi2018_tartu_q = quantize_raster(ndvi2018_tartu, n_levels = 16, method = "equal prob")
ndvi2023_tartu_q = quantize_raster(ndvi2023_tartu, n_levels = 16, method = "equal prob")
ndvi2018_tartu_textures = glcm_textures(ndvi2018_tartu_q, w = c(5, 5), na.rm = TRUE,
metrics = "glcm_homogeneity",
n_levels = 16, quantization = "none")
ndvi2023_tartu_textures = glcm_textures(ndvi2023_tartu_q, w = c(5, 5), na.rm = TRUE,
metrics = "glcm_homogeneity",
n_levels = 16, quantization = "none")
ndvi2023_tartu_textures_diff = ndvi2023_tartu_textures - ndvi2018_tartu_textures
plot(ndvi2023_tartu_textures_diff)Time for the above code chunk to run: 107.79 seconds
ndvi_diff = ndvi2023_tartu - ndvi2018_tartu
ndvi_diff_autocor = autocor(ndvi_diff, method = "moran", global = FALSE)
plot(ndvi_diff_autocor)Time for the above code chunk to run: 0.71 seconds
This example uses the SSIMmap package (Ha and Long 2023).
library(SSIMmap)
ndvi_ssim = ssim_raster(ndvi2018_tartu, ndvi2023_tartu, global = FALSE, w = 5)
plot(ndvi_ssim)Time for the above code chunk to run: 4.17 seconds
This example uses the rasterdiv package (Rocchini et al. 2021).
library(rasterdiv)
ndvi2018_tartu_int = ndvi2018_tartu * 100
ndvi2023_tartu_int = ndvi2023_tartu * 100
ndvi2018_tartu_rao = paRao(ndvi2018_tartu_int, window = 5, progBar = FALSE)
ndvi2023_tartu_rao = paRao(ndvi2023_tartu_int, window = 5, progBar = FALSE)
ndvi_rao_diff = ndvi2023_tartu_rao[[1]][[1]] - ndvi2018_tartu_rao[[1]][[1]]
plot(ndvi_rao_diff)Time for the above code chunk to run: 532.72 seconds
This example uses the yardstick package (Kuhn, Vaughan, and Hvitfeldt 2024).
library(yardstick)
ndvi_rmse = rmse_vec(values(ndvi2023_tartu)[,1], values(ndvi2018_tartu)[,1])
ndvi_rmse[1] 0.2191853
Time for the above code chunk to run: 0.13 seconds
This example uses the diffeR package (Pontius Jr. and Santacruz 2023).
library(diffeR)
ndvi_mad = MAD(ndvi2023_tartu, ndvi2018_tartu)[1] "The mean of grid1 is less than the mean of grid2"
ndvi_mad Resolution Quantity Strata Element Total
1 10 0.1783152 0 0.005990721 0.184306
Time for the above code chunk to run: 0.49 seconds
This example uses the philentropy (HG 2018) package.
library(philentropy)
softmax = function(x) {
exp_x = exp(x - max(x))
return(exp_x / sum(exp_x))
}
ndvi2023_tartu_vals = na.omit(values(ndvi2023_tartu)[,1])
ndvi2023_poznan_vals = na.omit(values(ndvi2023_poznan)[,1])
ndvi2023_tartu_vals_prob = softmax(ndvi2023_tartu_vals)
ndvi2023_poznan_vals_prob = softmax(ndvi2023_poznan_vals)
ndvi2023_tartu_vals_prob_interp = approx(seq_along(ndvi2023_tartu_vals_prob),
ndvi2023_tartu_vals_prob,
xout = seq_along(ndvi2023_poznan_vals_prob))$y
ndvi_mat = rbind(ndvi2023_poznan_vals_prob, ndvi2023_tartu_vals_prob_interp)
philentropy::distance(ndvi_mat, method = "kullback-leibler")kullback-leibler
0.028106
Time for the above code chunk to run: 0.2 seconds
This example uses the SSIMmap package (Ha and Long 2023).
library(SSIMmap)
ssim_raster(ndvi2018_tartu, ndvi2023_tartu, global = TRUE)SSIM: 0.63845 SIM: 0.90432 SIV: 0.90778 SIP: 0.75671
Time for the above code chunk to run: 1.12 seconds
This example uses the geodiv package (Smith et al. 2023).
library(geodiv)
ndvi2023_tartu_sa = sa(ndvi2023_tartu)
ndvi2023_poznan_sa = sa(ndvi2023_poznan)
abs(ndvi2023_tartu_sa - ndvi2023_poznan_sa)[1] 0.008087792
Time for the above code chunk to run: 0.1 seconds
This example uses the GLCMTextures package (Ilich 2020).
library(GLCMTextures)
ndvi2023_tartu_q = quantize_raster(ndvi2023_tartu, n_levels = 16, method = "equal prob")
ndvi2023_poznan_q = quantize_raster(ndvi2023_poznan, n_levels = 16, method = "equal prob")
ndvi2023_tartu_q_mat = as.matrix(ndvi2023_tartu_q, wide = TRUE)
ndvi2023_poznan_q_mat = as.matrix(ndvi2023_poznan_q, wide = TRUE)
ndvi2023_tartu_horizontal_glcm = make_glcm(ndvi2023_tartu_q_mat, n_levels = 16,
shift = c(1,0), na.rm = TRUE)
ndvi2023_poznan_horizontal_glcm = make_glcm(ndvi2023_poznan_q_mat, n_levels = 16,
shift = c(1,0), na.rm = TRUE)
ndvi2023_tartu_hom = glcm_metrics(ndvi2023_tartu_horizontal_glcm, "glcm_homogeneity")
ndvi2023_poznan_hom = glcm_metrics(ndvi2023_poznan_horizontal_glcm, "glcm_homogeneity")
abs(ndvi2023_tartu_hom - ndvi2023_poznan_hom)glcm_homogeneity
0.003689802
Time for the above code chunk to run: 0.69 seconds
This example uses the SpatialPack package (Vallejos, Osorio, and Bevilacqua 2020).
library(SpatialPack)
ndvi2023_tartu_mat = as.matrix(ndvi2023_tartu, wide = TRUE)
ndvi2023_poznan_mat = as.matrix(ndvi2023_poznan, wide = TRUE)
ndvi_CQ = CQ(ndvi2023_tartu_mat, ndvi2023_poznan_mat)
ndvi_CQ$CQTime for the above code chunk to run: 0 seconds
This example uses the bespatial package (Nowosad 2024).
library(bespatial)
ndvi2023_tartu_bes = bes_g_gao(ndvi2023_tartu, method = "hierarchy", relative = TRUE)
ndvi2023_poznan_bes = bes_g_gao(ndvi2023_poznan, method = "hierarchy", relative = TRUE)
abs(ndvi2023_tartu_bes$value - ndvi2023_poznan_bes$value)[1] 10611.69
Time for the above code chunk to run: 0.24 seconds
This example uses the keras3 (Kalinowski, Allaire, and Chollet 2024) and philentropy (HG 2018) packages.
library(keras3)
library(philentropy)
# keras3::install_keras(backend = "tensorflow")
normalize_raster = function(r) {
min_val = terra::global(r, "min", na.rm = TRUE)[[1]]
max_val = terra::global(r, "max", na.rm = TRUE)[[1]]
r = terra::app(r, fun = function(x) (x - min_val) / (max_val - min_val))
return(r)
}
ndvi2023n_tartu = normalize_raster(ndvi2023_tartu)
ndvi2023n_poznan = normalize_raster(ndvi2023_poznan)
ndvi2023_tartu_mat = as.matrix(ndvi2023n_tartu, wide = TRUE)
ndvi2023_poznan_mat = as.matrix(ndvi2023n_poznan, wide = TRUE)
ndvi2023_tartu_mat = array(rep(ndvi2023_tartu_mat, 3),
dim = c(nrow(ndvi2023_tartu_mat), ncol(ndvi2023_tartu_mat), 3))
ndvi2023_poznan_mat = array(rep(ndvi2023_poznan_mat, 3),
dim = c(nrow(ndvi2023_poznan_mat), ncol(ndvi2023_poznan_mat), 3))
model = keras3::application_vgg16(weights = "imagenet", include_top = FALSE,
input_shape = c(nrow(ndvi2023_tartu_mat), ncol(ndvi2023_tartu_mat), 3))
ndvi2023_tartu_mat = keras3::array_reshape(ndvi2023_tartu_mat, c(1, dim(ndvi2023_tartu_mat)))
ndvi2023_poznan_mat = keras3::array_reshape(ndvi2023_poznan_mat, c(1, dim(ndvi2023_poznan_mat)))
features2023_tartu = predict(model, ndvi2023_tartu_mat)1/1 - 2s - 2s/step
features2023_poznan = predict(model, ndvi2023_poznan_mat)1/1 - 2s - 2s/step
feature_map_tartu_1 = as.vector(features2023_tartu[1,,,1])
feature_map_poznan_1 = as.vector(features2023_poznan[1,,,1])
distance(rbind(feature_map_tartu_1, feature_map_poznan_1))euclidean
7.025183
Time for the above code chunk to run: 11.63 seconds
ndvi_diff = ndvi2023_tartu - ndvi2018_tartu
hist(ndvi_diff)Time for the above code chunk to run: 0.16 seconds
This example uses the waywiser package (Mahoney 2023).
library(waywiser)
cell_sizes = c(200, 400, 600)
ndvi_multi_scale = ww_multi_scale(truth = ndvi2018_tartu, estimate = ndvi2023_tartu,
metrics = list(yardstick::rmse),
cellsize = cell_sizes,
progress = FALSE)
ndvi_multi_scale# A tibble: 3 × 6
.metric .estimator .estimate .grid_args .grid .notes
<chr> <chr> <dbl> <list> <list> <list>
1 rmse standard 0.193 <tibble [1 × 1]> <sf [625 × 5]> <tibble [0 × 2]>
2 rmse standard 0.191 <tibble [1 × 1]> <sf [169 × 5]> <tibble [0 × 2]>
3 rmse standard 0.188 <tibble [1 × 1]> <sf [81 × 5]> <tibble [0 × 2]>
Time for the above code chunk to run: 3.55 seconds