I have a terra::rast()
stack of continuous data, which I classify to n classes, convert to factors and plot on a discrete scale.
But when the first raster does not have all the factors present that some of the other rasters do (e.g. only 3 classification values instead of the whole set of 10, converted to factors), the plot goes a bit haywire.
I am looking for a way to inform the rast stack (or plot) that the levels of the whole stack are min - max of the the stack, but some layers may have less.
Interestingly, if the 1st layer has all classes/factors possible then the subsequent ones are ok and the plot is fine.
# dummy data
library(terra)
r1 <- rast(nrows = 10, ncols = 10, xmin = 0, xmax = 10, ymin = 0, ymax = 10)
r1[] <- runif(ncell(r1), min = 1, max = 5) # Random values between 1 and 5
r2 <- rast(nrows = 10, ncols = 10, xmin = 0, xmax = 10, ymin = 0, ymax = 10)
r2[] <- runif(ncell(r2), min = 1, max = 5)
# Combine rasters into a stack
s <- c(r1/r1, r1/r2, r2/r1, r2/r2)
names(s) <- c("r1/r1", "r1/r2", "r2/r1", "r2/r2")
# Reclassify the raster stack
# Define reclassification matrix
m_rc <- matrix(c(0, 0.5, 1,
0.5, 0.9, 2,
0.9, 1.1, 3,
1.1, 2, 4,
2, max(global(s, max, na.rm=T)$max), 5),
ncol = 3, byrow = TRUE)
# Apply reclassification
s_r <- classify(s, m_rc)
# Convert reclassified raster to factor for categorical plotting
s_r_f <- as.factor(s_r)
# Step 3: Plot using ggplot2 and tidyterra with custom legend labels
ggplot() +
geom_spatraster(data = s_r_f) +
facet_wrap(~lyr, nrow = 2) + # Separate plots for each layer
scale_fill_manual(
values = c("blue","lightblue" , "white", "yellow", "red"), # Assign custom colors
na.value = "transparent", # Transparent for NA values
) +
labs(
title = "Reclassified Raster Stack",
labels = c("0 - 0.5","0.5 - 0.9","0.9 - 1.1","1.1 - 2","> 2"),
fill = "Class"
) +
theme_minimal()
That should be improved a bit in the package, but right now you can do this:
# set the same levels to all layers
x <- categories(x, 0, levels(s_r_f)[[2]])
panel(x, all_levels=TRUE, col = c("blue","lightblue", "white", "yellow", "red"), main=1:4)
With the development version of terra (version 1.8-9) you can now do
panel(s_r_f, col = c("blue","lightblue", "white", "yellow", "red"))
And for use with tidyterra and ggplot you can first use combineLevels
x <- combineLevels(s_r_f)
library(tidyterra)
library(ggplot2)
ggplot() +
geom_spatraster(data = x) +
facet_wrap(~lyr, nrow = 2) + # Separate plots for each layer
scale_fill_manual(
values = c("blue","lightblue" , "white", "yellow", "red"), # Assign custom colors
na.value = "transparent", # Transparent for NA values
) +
labs(
title = "Reclassified Raster Stack",
labels = c("0 - 0.5","0.5 - 0.9","0.9 - 1.1","1.1 - 2","> 2"),
fill = "Class"
) +
theme_minimal()