rggplot2plotterratidyterra

Customizing legend when plotting plotting geom_spatraster and geom_spatvector in R


Using R, I am attempting to create a plot that contains both geom_spatraster and geom_spatvector objects, and I am running into issues with the legend. Using the repex at the bottom below, the legend for the pts points show up in every color from the spatraster (first screenshot below). (I'm not needing to include the pol variable in the legend.) Is there a way to plot the pts spatvector variable and have it listed separately in the legend, like the second screenshot below?

current plot output desired plot output

library(terra)
library(tidyterra)
library(ggplot2)

#create raster
df <- data.frame(x=rep(c(0.5,1.5,2.5), by=3),
           y=rep(c(3.5, 2.5, 1.5, 0.5), each=3),
           z = 1:12)

r <- rast(df, type="xyz", crs="epsg:4326")

#raster color table
ctbl <- data.frame(value=1:12,
                   col=colors()[sample.int(length(colors()), 12, replace = FALSE)])
coltab(r) <- ctbl    #apply to raster

cls <- data.frame(id    = 1:12,
                  cat = letters[1:12])
levels(r) <- cls         #apply to raster
plot(r)

#create "state" polygon
pol <- vect(list(rbind(c(0.5,3.5), c(0.5,0.5), c(2.5,0.5), c(2.5,3.5), c(0.5,3.5))),
            "polygons",
            crs="epsg:4326")
pol$name <- "state name"
plot(pol, add=TRUE)
#create "station" points
pts <- vect(list(rbind(c(2,2), c(1.5,3.2), c(0.6,2.8))),
            "points",
            crs="epsg:4326")
pts$stn_names <- sprintf("station %s", 1:3)
plot(pts, add=TRUE)

#plot
ggplot() +
  geom_spatraster(data=r,
                  use_coltab=TRUE,
                  name="Land cover") +
  geom_spatvector(data = pol,
                  fill = NA,
                  linewidth=0.8,
                  color="#282828", 
                  show.legend=FALSE) +
  geom_spatvector(data=pts, 
                  shape=24, size=3, 
                  col="black", 
                  fill="magenta", 
                  show.legend = TRUE)  

Solution

  • To get a separate legend map on the shape aesthetic instead of setting the shape as a parameter and use e.g. scale_shape_identity. Additionally I explicitly set the order of the legends via guide_legend.

    library(terra)
    library(tidyterra)
    library(ggplot2)
    
    set.seed(456)
    
    ggplot() +
      geom_spatraster(
        data = r,
        use_coltab = TRUE
      ) +
      geom_spatvector(
        data = pol,
        fill = NA,
        linewidth = 0.8,
        color = "#282828",
        show.legend = FALSE
      ) +
      geom_spatvector(
        data = pts,
        aes(shape = 24),
        size = 3,
        color = "black",
        fill = "magenta"
      ) +
      scale_shape_identity(
        labels = "Stations",
        guide = guide_legend(order = 2), 
        name = NULL
      ) +
      labs(fill = "Land cover") +
      guides(fill = guide_legend(order = 1)) +
      theme(
        # Remove grey bg
        legend.key = element_rect(fill = NA),
        # Uncomment to remove the space between the legends
        #legend.spacing.y = unit(0, "pt"),
        #legend.margin = margin()
      )
    

    enter image description here