I want to be able truncate the colour pallete for certain values of a raster using ggplot, which I am able to do using basic plotting of the terra object, but not with ggplot2.
This is what I have been able to produce
library(terra)
library(tidyterra)
library(ggplot2)
rast1 <- rast(ncol=100, nrow=100, nlyr=1)
rast1 <- init(rast1, "cell")
rast1 <- spatSample(rast1, ncell(rast1), "random", as.raster=TRUE)
#full raster with basic terra plotting
plot(rast1)
#try to truncate values for better viz
mean.val <- mean(terra::values(rast1), na.rm = TRUE)
low.val<- min(terra::values(rast1), na.rm = TRUE)
zmin <- max(mean.val, 0.001, na.rm = TRUE)
zmin <- max(zmin, 0.01, na.rm = TRUE)
zmax <- max(terra::values(rast1), na.rm = TRUE)
q99 <- quantile(terra::values(rast1), probs=c(0.999), na.rm=TRUE)
#Truncated raster using terra base plotting
plot(rast1, col = whitebox.colors(100), range=c(zmin,q99), axes=FALSE)
#plotting high values
plot(rast1, col="#255668", range=c(q99,zmax), axes=FALSE, legend=FALSE, add=TRUE)
#plotting low values
plot(rast1, col="#F9FFAF", range=c(low.val,zmin), axes=FALSE, legend=FALSE, add=TRUE)
Which produces this output desired ouput
#So far I can only set limits with ggplot
#mid values
ggplot() +
geom_spatraster(data = rast1) +
scale_fill_whitebox_c(limits = c(zmin,q99))
I would need to incorporate the remaining colors for the highest and lowest range of values. But I staill haven't figure out how to do it, without "reclassifying" the data, and I still think it may be a bit tricky because I only want to truncate to a high and low value, but retain the full range of mid values. Which I believe reclassifying wont really do.
Any input would be greatly appreciated!
One possible option would be to create a custom color scale using
scale_fill_gradientn
(which under the hood is also used byscale_fill_whitebox_c
). The vectors to be passed to thecolors=
andvalues=
argument are pretty straightforward with the exception that thevalues=
argument requires a vector in the rangec(0, 1)
and hence require some rescaling. Finally, setoob = scales::oob_squish
which in contrast to the defaultoob_censor
"squishes" values which fall outside of the limits into the range of the scale. This way the low values are assigned the low color and the high values the high color. There is still a small drawback though as the low and (especially) the high color are visible in the legend if you take a close look.