Plot multiple shapefiles

Last updated on 2024-12-03 | Edit this page

Overview

Questions

  • How can I create map compositions with custom legends using ggplot?

Objectives

After completing this episode, participants should be able to…

  • Plot multiple vector layers in the same plot.
  • Apply custom symbols to spatial objects in a plot.

This episode builds upon the previous episode to work with vector layers in R and explore how to plot multiple vector layers.

Load the data


To work with vector data in R, we use the sf library. Make sure that it is loaded.

We will continue to work with the three ESRI shapefiles that we loaded in the Open and Plot Vector Layers episode.

Plotting Multiple Vector Layers


So far we learned how to plot information from a single shapefile and do some plot customization. What if we want to create a more complex plot with many shapefiles and unique symbols that need to be represented clearly in a legend?

We will create a plot that combines our leisure locations (point_Delft), municipal boundary (boundary_Delft) and streets (lines_Delft) spatial objects. We will need to build a custom legend as well.

To begin, we will create a plot with the site boundary as the first layer. Then layer the leisure locations and street data on top using +.

R

ggplot() +
  geom_sf(
    data = boundary_Delft,
    fill = "lightgrey",
    color = "lightgrey"
  ) +
  geom_sf(
    data = lines_Delft_selection,
    aes(color = highway),
    size = 1
  ) +
  geom_sf(data = point_Delft) +
  labs(title = "Mobility network of Delft") +
  coord_sf(datum = st_crs(28992))

Next, let’s build a custom legend using the functions scale_color_manual() and scale_fill_manual().

R

leisure_colors <- rainbow(15)
point_Delft$leisure <- factor(point_Delft$leisure)

ggplot() +
  geom_sf(
    data = boundary_Delft,
    fill = "lightgrey",
    color = "lightgrey"
  ) +
  geom_sf(
    data = lines_Delft_selection,
    aes(color = highway),
    size = 1
  ) +
  geom_sf(
    data = point_Delft,
    aes(fill = leisure),
    shape = 21
  ) +
  scale_color_manual(
    values = road_colors,
    name = "Road Type"
  ) +
  scale_fill_manual(
    values = leisure_colors,
    name = "Lesiure Location"
  ) +
  labs(title = "Mobility network and leisure in Delft") +
  coord_sf(datum = st_crs(28992))

R

ggplot() +
  geom_sf(
    data = boundary_Delft,
    fill = "lightgrey",
    color = "lightgrey"
  ) +
  geom_sf(
    data = lines_Delft_selection,
    aes(color = highway),
    size = 1
  ) +
  geom_sf(
    data = point_Delft,
    aes(fill = leisure),
    shape = 22
  ) +
  scale_color_manual(
    values = road_colors,
    name = "Line Type"
  ) +
  scale_fill_manual(
    values = leisure_colors,
    name = "Leisure Location"
  ) +
  labs(title = "Mobility network and leisure in Delft") +
  coord_sf(datum = st_crs(28992))

We notice that there are quite some playgrounds in the residential parts of Delft, whereas on campus there is a concentration of picnic tables. So that is what our next challenge is about.

Challenge: Visualising multiple layers with a custom legend

Create a map of leisure locations only including playground and picnic_table, with each point colored by the leisure type. Overlay this layer on top of the lines_Delft layer (the streets). Create a custom legend that applies line symbols to lines and point symbols to the points.

Modify the plot above. Tell R to plot each point, using a different symbol of shape value.

R

leisure_locations_selection <- st_read("data/delft-leisure.shp") %>%
  filter(leisure %in% c("playground", "picnic_table"))

OUTPUT

Reading layer `delft-leisure' from data source
  `/home/runner/work/r-geospatial-urban/r-geospatial-urban/site/built/data/delft-leisure.shp'
  using driver `ESRI Shapefile'
Simple feature collection with 298 features and 2 fields
Geometry type: POINT
Dimension:     XY
Bounding box:  xmin: 81863.21 ymin: 442621.1 xmax: 87370.15 ymax: 449345.1
Projected CRS: Amersfoort / RD New

R

levels(factor(leisure_locations_selection$leisure))

OUTPUT

[1] "picnic_table" "playground"  

R

blue_orange <- c("cornflowerblue", "darkorange")

R

ggplot() +
  geom_sf(
    data = lines_Delft_selection,
    aes(color = highway)
  ) +
  geom_sf(
    data = leisure_locations_selection,
    aes(fill = leisure),
    shape = 21
  ) +
  scale_color_manual(
    name = "Line Type",
    values = road_colors,
    guide = guide_legend(override.aes = list(
      linetype = "solid",
      shape = NA
    ))
  ) +
  scale_fill_manual(
    name = "Soil Type",
    values = blue_orange,
    guide = guide_legend(override.aes = list(
      linetype = "blank",
      shape = 21,
      colour = NA
    ))
  ) +
  labs(title = "Traffic and leisure") +
  coord_sf(datum = st_crs(28992))

R

ggplot() +
  geom_sf(
    data = lines_Delft_selection,
    aes(color = highway),
    size = 1
  ) +
  geom_sf(
    data = leisure_locations_selection,
    aes(fill = leisure, shape = leisure),
    size = 2
  ) +
  scale_shape_manual(
    name = "Leisure Type",
    values = c(21, 22)
  ) +
  scale_color_manual(
    name = "Line Type",
    values = road_colors
  ) +
  scale_fill_manual(
    name = "Leisure Type",
    values = rainbow(15),
    guide = guide_legend(override.aes = list(
      linetype = "blank",
      shape = c(21, 22),
      color = "black"
    ))
  ) +
  labs(title = "Road network and leisure") +
  coord_sf(datum = st_crs(28992))

Key Points

  • Use the + operator to add multiple layers to a ggplot.
  • A plot can be a combination of multiple vector layers.
  • Use the scale_color_manual() and scale_fill_manual() functions to set legend colors.