I have a SpatRast
object that contains a positive variable with a lower bound at 0. However, values below 1.3 indicate spatial dispersion, whereas values above 1.3 indicate spatial concentration. Therefore, I would like to map this raster using a color scale that diverges at 1.3. The values would need to be mapped in two distinct ways, that is continuously and in intervals; however, for both of these representations, the resulting legend would need to show 0 at the bottom and the maximum value at the top.
Despite my various attempts, I cannot manage to obtain what I want. Here I report a minimal example and the resulting figure using an interval representation, in which however I am unable to display the legend in reverse order. I would then also need to produce the corresponding representation treating the variable as continuous.
I am not bound to any specific library. With terra
it seems impossible to reverse the legend order and it also seems impossible to obtain a non-linear customization of the color scale when the variable is to be plotted continuously. But I have tried also with rasterVis
and ggplot2
, and in each of these cases I have stumbled upon other obstacles. Also, in my example I obtain the color palette with RColorBrewer
, but again I am not specifically bound to this library.
Can anybody help me? Thanks.
library(RColorBrewer)
bks <- c(0,0.4,0.8,1.3,2,4,8,15,30)
cold <- rev(RColorBrewer::brewer.pal(3, "Blues"))
warm <- RColorBrewer::brewer.pal(((length(bks)-1)-length(cold)), "Reds")
colors <- c(cold, warm)
terra::plot(x,
breaks = bks,
col = colors,
box=F,
axes=F)
Example data:
library(terra)
r <- rast(system.file("ex/elev.tif", package="terra"))
x <- scale_linear(r, 0, 30)
bks <- c(0,0.4,0.8,1.3,2,4,8,15,30)
colors <- c('#3182BD', '#9ECAE1', '#DEEBF7', '#FEE5D9', '#FCAE91',
'#FB6A4A', '#DE2D26', '#A50F15')
With terra > 1.8-36, you can reverse the interval legend like this:
plot(x, col=colors, box=F, axes=F, breaks=bks, reverse=TRUE)
# or
plot(classify(x, bks), col=colors, box=F, axes=F, reverse=TRUE)
With prior versions, you can achieve this by creating a categorical raster and use argument "sort" like this:
b <- classify(x, bks)
ord <- rev(levels(b)[[1]][,2])
terra::plot(b, col = colors, box=F, axes=F, sort=ord)
For the continuous legend, you can make two color palettes, and then create colors with each, proportionally to the range of values before and after the break
crp1 <- colorRampPalette(colors[1:3])
crp2 <- colorRampPalette(colors[4:8])
cols <- c(crp1(10), crp2(10 * (30-1.3)/1.3))
plot(x, col=cols, plg=list(at=c(0,1.3, 5, 10, 20, 30), digits=1),
range=c(0,30), axes=FALSE)