'Common colour and legend for multiple categorical rasters
I want to make a multipanel plot of 3 rasters with categorical values. is there a way where I can automatically draw breaks, and colors for each raster? I have a reproducible example below with three rasters r1,r2, and r3. r1 has values from 0to 5, r2 has values 0,13,4 and r3 has values 0,1,2,4. I want to save myself from specifying the color panel for each raster separately.
Thanks in advance
library(raster)
# Define the rasters
r1 <- raster(nrow=5, ncol=5)
x1<- c(0,1,2,3,4,5)
values(r1) <- sample(x1, ncell(r1), replace=TRUE)
r2 <- raster(nrow=5, ncol=5)
x2<- c(0,1,3,4)
values(r2) <- sample(x2, ncell(r2), replace=TRUE)
as.factor(r2)
r3 <- raster(nrow=5, ncol=5)
x3<- c(0,1,2,4)
values(r3) <- sample(x3, ncell(r3), replace=TRUE)
as.factor(r3)
# creating the breaks and colour vectors
br1 <- c(0,1,2,3,4,5)
cl1 <- c("red","orange","green","blue","gray", "brown")
br2 <- c(0,1,3,4)
cl2 <- c("red","orange","blue","gray")
br3 <- c(0,1,2,4)
cl3 <- c("red","orange","green","brown")
# Create the multi plot
par(mfrow=c(1,3),xpd=T)
plot(r1,col=cl1,legend=F,axes=F,asp=NA)
text(r1,cex=1)
plot(r1,legend.only=T, breaks=br1,col = cl1,bty="n",xpd=T)
plot(r2,col=cl2,legend=F,axes=F,asp=NA)
text(r2,cex=1)
plot(r2,legend.only=T, breaks=br2,col = cl2,bty="n",xpd=T)
plot(r3, col=cl3,legend=F,axes=F,asp=NA)
text(r3, cex=1)
plot(r3, legend.only=T, breaks=br3,col = cl3,bty="n",xpd=T)
Solution 1:[1]
There might be more efficient ways to plot raster panels or facets, e.g. ?plot::raster suggests that the rasterVis package offers more advanced plotting functions for raster objects, including trellis/lattice plots.
However, the following solution aims at avoiding repeated code as indicated in your question and stays close to the original. Here, a custom function and lists, as well as lapply(), are used.
library(raster)
# Define the rasters
r1 <- raster(nrow = 5, ncol = 5)
x1 <- c(0, 1, 2, 3, 4, 5)
values(r1) <- sample(x1, ncell(r1), replace = TRUE)
br1 <- c(0, 1, 2, 3, 4, 5)
cl1 <- c("red", "orange", "green", "blue", "gray", "brown")
r2 <- raster(nrow = 5, ncol = 5)
x2 <- c(0, 1, 3, 4)
values(r2) <- sample(x2, ncell(r2), replace = TRUE)
r2_2 <- r2
as.factor(r2) # as.factor() does not modify the object r2 in place.
identical(r2, r2_2)
r3 <- raster(nrow = 5, ncol = 5)
x3 <- c(0, 1, 2, 4)
values(r3) <- sample(x3, ncell(r3), replace = TRUE)
# creating the breaks and colour vectors
br1 <- c(0, 1, 2, 3, 4, 5)
cl1 <- c("red", "orange", "green", "blue", "gray", "brown")
raster_list_1 <- list(r1, br1, cl1)
br2 <- c(0, 1, 3, 4)
cl2 <- c("red", "orange", "blue", "gray")
raster_list_2 <- list(r2, br2, cl2)
br3 <- c(0, 1, 2, 4)
cl3 <- c("red", "orange", "green", "brown")
raster_list_3 <- list(r3, br3, cl3)
raster_listoflists <-
list(raster_list_1, raster_list_2, raster_list_3)
# Create the multi plot
plot_raster_panels <- function(rasterlists) {
list_size <- length(rasterlists)
mfrow_before <- par("mfrow")
par(mfrow = c(1, list_size), xpd = TRUE)
lapply(rasterlists, function(x) {
raster_layer <- x[[1]]
breaks <- x[[2]]
colours <- x[[3]]
plot(
raster_layer,
col = colours,
legend = FALSE,
axes = FALSE,
asp = NA
)
text(raster_layer, cex = 1)
plot(
raster_layer,
legend.only = TRUE,
breaks = breaks,
col = colours,
bty = "n",
xpd = TRUE
)
})
on.exit(par(mfrow = mfrow_before))
invisible(0)
}
plot_raster_panels(raster_listoflists)
Some remarks and suggestions:
- I would advise you to aim for a consistent coding style, e.g. don't mix
argument = Tandargument = TRUE. You should probably avoid usingTandFaltogether, as they are just aliases toTRUEandFALSErespectively and can be reassigned by users. - Use instructive names for variables. No one, not even you in a few months, is going to remember what br1 and cl1 stand for. Use descriptive verbs for functions and nouns that describe content for objects and
snake_casefor objects, as suggested in Tidyverse Style Guide. - You use
as.factor(raster_object)in your script but do not assign it. If you want to inspect the result interactively, this is fine. However, be aware that most R functions do not modify objects in place, i.e. the objects are immutable, and you have to assign the result to a new object. A notable exception to this is theR6package and its functions (Advanced R - R6). - I am using lists in my solution and not vectors because lists can, as opposed to vectors, hold different types of data (cf. An Introduction to R - Lists).
- It is not possible to save the plot of R base plot functions directly into an object since they return
NULLor computed values instead (e.g.(plot(1))). To avoid printingNULLto the console, I have usedinvisible(0)to return an arbitrary number (0 is, however, conventionally used in function returns to signal normal execution). - Since we want to keep the plot after the function has run, we can't turn off the graphic device (
dev.off()) inside our function. Thus we should reset themfrowparameter that we changed for the multi-panel plot.
Edit: Edited for clarity, added syntax highlighting and references.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
