Search code examples
rggplot2legendr-sfggspatial

How to customize legend in ggplot for multiple layers in a map?


I'm trying to fix my caption but I'm having trouble creating it. I wanted a caption for the classes (fill), the shape limit (color), the points (color) and the grid (fill=NA). I put them all in aes () but I don't have the expected result. Can anybody help me? Thanks!

library(geobr)
library(sf)
library(ggplot2)
library(ggspatial)

#Directory

getwd()

#Download spatial data ------------------------------------------------

download.file(url = "http://geo.fbds.org.br/SP/RIO_CLARO/USO/SP_3543907_USO.dbf", 
              destfile = "SP_3543907_USO.dbf", mode = "wb")
download.file(url = "http://geo.fbds.org.br/SP/RIO_CLARO/USO/SP_3543907_USO.prj", 
              destfile = "SP_3543907_USO.prj", mode = "wb")
download.file(url = "http://geo.fbds.org.br/SP/RIO_CLARO/USO/SP_3543907_USO.shp", 
              destfile = "SP_3543907_USO.shp", mode = "wb")
download.file(url = "http://geo.fbds.org.br/SP/RIO_CLARO/USO/SP_3543907_USO.shx", 
              destfile = "SP_3543907_USO.shx", mode = "wb")

#Import spatial data --------------------------------------------------

uso <- sf::st_read("SP_3543907_USO.shp")
uso
plot(uso$geometry)

#Area limit

rio_claro_limit <- geobr::read_municipality(code_muni = 3543907, year = 2015)
rio_claro_limit
plot(rio_claro_limit$geom)

#Random sample points

set.seed(123)
pts <- st_sample(uso, size = 20, type="random") %>% st_sf

#Grid 50km x 50km

grid_50 <- st_make_grid(uso, cellsize = c(5000, 5000)) %>% 
  st_sf(grid_id = 1:length(.))

#Labels grid

grid_lab <- st_centroid(grid_50) %>% cbind(st_coordinates(.))

#Points in grid

pts %>% st_join(grid_50, join = st_intersects) %>% as.data.frame


#Map --------------------------------------------------------------------

ggplot() +
  geom_sf(data = uso, aes(fill = CLASSE_USO, color = NA)) +
  geom_sf(data = rio_claro_limit, aes(color = 'black', fill = NA)) +
  geom_sf(data = pts, aes(color = 'red'), size = 1.7) + 
  geom_sf(data = grid_50, aes(fill=NA), lwd = 0.3) +
  geom_text(data = grid_lab, aes(x = X, y = Y, label = grid_id), size = 2) +
  xlab("")+
  ylab("")+
  scale_fill_manual(name="Classes de Uso", values = c("blue", "orange", "gray30", "forestgreen", "green", NA))+
  scale_color_identity(guide = "legend")

enter image description here


Solution

  • Your desired result could be achieved like so:

    1. I moved all fill=NA and color=NA out of the aes() statements. As usual if you want to fix a color, fill or more generally any aes on a specific value then it's best to put it outside of aes() except for the case that you want it to appear in the legend.

    2. Set the so called key_glyph, i.e. the icon drawn in the legend, of the "point" layers to "point".

    As these steps also removed the black border around the fill keys I added a guides layer to get that back. Personally I would remove the black border, but hey, it's your plot. (:

    library(geobr)
    library(sf)
    library(ggplot2)
    library(ggspatial)
    
    ggplot() +
      geom_sf(data = uso, aes(fill = CLASSE_USO), color = NA) +
      geom_sf(data = rio_claro_limit, aes(color = 'black'), fill = NA, key_glyph = "point") +
      geom_sf(data = pts, aes(color = 'red'), size = 1.7, key_glyph = "point") + 
      geom_sf(data = grid_50, fill = NA, lwd = 0.3) +
      geom_text(data = grid_lab, aes(x = X, y = Y, label = grid_id), size = 2) +
      xlab("")+
      ylab("")+
      scale_fill_manual(name="Classes de Uso", values = c("blue", "orange", "gray30", "forestgreen", "green", NA)) +
      guides(fill = guide_legend(override.aes = list(color = "black"))) +
      scale_color_identity(guide = "legend")