13  Advanced tmap

We’ve already made many simple maps using the tmap package. Now that we know more about cartographic design, we can explore the more advanced features of tmap. This chapter does not cover everything. For much more information on making good maps in tmap, this is a great resource: Spatial Data Visualization with tmap

After completing these exercises, you should be able to:

We will use our NC county boundary and Durham schools data to practice our tmap visualization.

library(tidyverse)
library(sf)
library(tmap)

nc_counties <- st_read("https://drive.google.com/uc?export=download&id=1g9sGIikgOEubqoj97fUVoCYAKlBDVX5a")

durham_schools <- st_read("https://drive.google.com/uc?export=download&id=1ajKBLeKpFMW8z0HCbnLi4C44tgryCsRt") 

13.1 Visual Variables

13.1.1 Color

We are already familiar with making a basic tmap using color to visualize patterns:

tm_shape(nc_counties) + tm_polygons(fill = "POP2020")

13.1.2 Size

We can also represent variables by size

tm_shape(nc_counties) + tm_symbols(size = "POP2020")

13.1.3 Size and Color

Or both!

tm_shape(nc_counties) + tm_symbols(size = "POP2020", fill = "POP2020")

13.1.4 Shape

For categorical variables, we can also use shape

#with symbols there are a default of 5 symbols. If you have more than 5 categories, you need to specify which shapes to use using the shape.scale() argument
tm_shape(durham_schools) + tm_symbols(shape = "factype", shape.scale = tm_scale(values = c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)))

13.2 Color Palettes

We can also modify the color palette. To see all the available color palettes, you should run the command below

cols4all::c4a_gui()
tm_shape(nc_counties) + tm_polygons(fill = "POP2020", fill.scale = tm_scale_intervals(values = "bu_pu"))

13.3 Classification Schemes

One of the biggest decisions we can make is how to classify our data. You can see in the maps above that tmap defaults to an equal interval color scheme. However, this is often not the best way to classify the data. Your decision about classification should be made based on the distribution of the data. Let’s look at the distribution of the median age variable

ggplot(nc_counties, aes(x = POP2020)) + geom_histogram()

Because so much of our variation is between below 200,000, using an equal interval color palette makes it difficult to visualize the majority of the variation. See how different the map looks when we use a quantile classification scheme?

tm_shape(nc_counties) + tm_polygons(fill = "POP2020", fill.scale = tm_scale_intervals(values = "bu_pu", style = "quantile"))

The following classification schemes will cover most of your uses:

  • equal
  • pretty
  • quantile
  • fisher (natural breaks)

13.4 Interactive Mapping

So far, we have only made mostly static maps. However, tmap has the availability to make interactive maps as well.

## make an interactive map
tmap_mode(mode = "view")

tm_shape(nc_counties) + tm_polygons(fill = "POP2020", fill.scale = tm_scale_intervals(values = "bu_pu", style = "quantile"))

13.5 Multiple Layers

You can add as many layers to a tmap as you want

#turn back to non-interactive
tmap_mode("plot")

durham_county <- nc_counties |> filter(NAME == "Durham")
tm_shape(durham_county) + tm_borders() + tm_shape(durham_schools) + tm_dots()

13.6 Formatting

13.6.1 Adding Transparency and additional classes

tm_shape(nc_counties) + tm_polygons(fill = "POP2020", fill_alpha = .3, fill.scale = tm_scale_intervals(values = "bu_pu", style = "quantile", n = 7))

13.6.2 Adding a Basemap and a Title

tm_shape(nc_counties) + tm_polygons(fill = "POP2020",fill.scale = tm_scale_intervals(values = "bu_pu", style = "quantile", n = 5), fill_alpha = .3) +
tm_title("Median Age by Census Block Group") + tm_basemap("OpenStreetMap")

The following basemaps will cover most of your uses:

  • “CartoDB.VoyagerOnlyLabels” - Labels Only
  • “CartoDB.PositronNoLabels”- No Labels
  • “OpenStreetMap” - Labeled Basemap
  • “Esri.WorldImagery” - Satellite

13.7 Layout

tmap provides advanced functionality for map formatting, which is explored in greater detail here. For example, we can make substantially improve the formatting of the map above

tm_shape(nc_counties) +
  tm_polygons(
    fill = "POP2020",
    fill.scale = tm_scale_intervals(
      values = "bu_pu",
      style = "quantile",
      n = 5
    ),
    fill_alpha = 0.3,
    fill.legend = tm_legend(
      position = tm_pos_in("left", "bottom"),
      frame = TRUE,
      frame.r = 6,
      bg.color = "white",
      item.height = 0.55,
      item.width  = 0.55
    )
  ) +
  tm_title("2020 Population by NC County", size = 2) +
  tm_basemap("OpenStreetMap") +
  tm_layout(
    text.fontfamily = "serif",
    frame = TRUE,
    frame.r = 15
  )
Multiple palettes called "bu_pu" found: "brewer.bu_pu", "matplotlib.bu_pu". The first one, "brewer.bu_pu", is returned.

13.8 Map Competition

In this exercise, you will create a well-designed map that leverages the stylistic and formatting capabilities of the tmap package. You will likely want to add formatting components that we have not explicitly covered. See Spatial Data Visualization with tmap for additional assistance.

13.8.1 Map Prompt: Create a well-designed map of weekend bus serviceability to Chapel Hill parks

ch_boundary <- st_read("https://drive.google.com/uc?export=download&id=1ievfdMpmrZBO1qBI_uILYpb1XbVXmC0b")

num_weekend_buses <- st_read("https://drive.google.com/uc?export=download&id=1sm1wakDXNoHQjXHhScH7Q5QdgqRvZTCD")

parks <- st_read("https://drive.google.com/uc?export=download&id=1WfzXK_3NZsll9ov8uD5-9i8ceVMlEUlN")