In this lab, we’ll explore the basics of map-making in R using the tmap package. The following materials are modified from Chapter 9 of Geocomputation with R by Rovin Lovelace
Let’s load all necessary packages.
#install.packages("sf")
#install.packages("terra")
#install.packages("spData")
#install.packages("spDataLarge", repos = "https://geocompr.r-universe.dev")
#remotes::install_github("r-tmap/tmap@v4")
library(sf)
library(terra)
library(dplyr)
library(spData)
library(spDataLarge)
library(tmap) # for static and interactive maps
Let’s also read in some data from the spDataLarge package to work with later.
nz_elev = rast(system.file("raster/nz_elev.tif", package = "spDataLarge"))
Let’s start with a pre-loaded spatial object representing the states of New Zealand
nz
## Simple feature collection with 16 features and 6 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 1090144 ymin: 4748537 xmax: 2089533 ymax: 6191874
## Projected CRS: NZGD2000 / New Zealand Transverse Mercator 2000
## First 10 features:
## Name Island Land_area Population Median_income Sex_ratio
## 1 Northland North 12500.561 175500 23400 0.9424532
## 2 Auckland North 4941.573 1657200 29600 0.9442858
## 3 Waikato North 23900.036 460100 27900 0.9520500
## 4 Bay of Plenty North 12071.145 299900 26200 0.9280391
## 5 Gisborne North 8385.827 48500 24400 0.9349734
## 6 Hawke's Bay North 14137.524 164000 26100 0.9238375
## 7 Taranaki North 7254.480 118000 29100 0.9569363
## 8 Manawatu-Wanganui North 22220.608 234500 25000 0.9387734
## 9 Wellington North 8048.553 513900 32700 0.9335524
## 10 West Coast South 23245.456 32400 26900 1.0139072
## geom
## 1 MULTIPOLYGON (((1745493 600...
## 2 MULTIPOLYGON (((1803822 590...
## 3 MULTIPOLYGON (((1860345 585...
## 4 MULTIPOLYGON (((2049387 583...
## 5 MULTIPOLYGON (((2024489 567...
## 6 MULTIPOLYGON (((2024489 567...
## 7 MULTIPOLYGON (((1740438 571...
## 8 MULTIPOLYGON (((1866732 566...
## 9 MULTIPOLYGON (((1881590 548...
## 10 MULTIPOLYGON (((1557042 531...
the first element is always “tm_shape”
tm_shape(nz) +
tm_fill()
now let’s plot just the boundaries
tm_shape(nz) +
tm_borders()
and the shapes and boundaries together
tm_shape(nz) +
tm_fill() +
tm_borders()
map_nz <- tm_shape(nz) +
tm_polygons()
class(map_nz)
## [1] "tmap"
In this case, we’re adding a layer with information on elevation and this layer to have 70% transparency.
map_nz1 <- map_nz +
tm_shape(nz_elev) +
tm_raster(col_alpha = 0.7)
map_nz1
## SpatRaster object downsampled to 1141 by 877 cells.
we can add points designating high points in the country
map_nz2 <- map_nz1 +
tm_shape(nz_height) +
tm_dots()
map_nz2
## SpatRaster object downsampled to 1141 by 877 cells.
Let’s start by changing some fixed aesthetics…First, let’s change the color used to fill the NZ shapes.
tm_shape(nz) +
tm_polygons(fill = "red")
now change the color of the boundaries
tm_shape(nz) +
tm_polygons(col = "blue")
and the width of the boundary lines
tm_shape(nz) +
tm_polygons(lwd = 3)
and the line type of the boundary lines
tm_shape(nz) +
tm_polygons(lty = 2)
all together now!
tm_shape(nz) +
tm_polygons(fill = "red",
fill_alpha = 0.3,
col = "blue",
lwd = 3,
lty = 2)
Now let’s change the colors based on a value. We noticed that the New Zealand dataset has a column with each state’s land area
nz
## Simple feature collection with 16 features and 6 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 1090144 ymin: 4748537 xmax: 2089533 ymax: 6191874
## Projected CRS: NZGD2000 / New Zealand Transverse Mercator 2000
## First 10 features:
## Name Island Land_area Population Median_income Sex_ratio
## 1 Northland North 12500.561 175500 23400 0.9424532
## 2 Auckland North 4941.573 1657200 29600 0.9442858
## 3 Waikato North 23900.036 460100 27900 0.9520500
## 4 Bay of Plenty North 12071.145 299900 26200 0.9280391
## 5 Gisborne North 8385.827 48500 24400 0.9349734
## 6 Hawke's Bay North 14137.524 164000 26100 0.9238375
## 7 Taranaki North 7254.480 118000 29100 0.9569363
## 8 Manawatu-Wanganui North 22220.608 234500 25000 0.9387734
## 9 Wellington North 8048.553 513900 32700 0.9335524
## 10 West Coast South 23245.456 32400 26900 1.0139072
## geom
## 1 MULTIPOLYGON (((1745493 600...
## 2 MULTIPOLYGON (((1803822 590...
## 3 MULTIPOLYGON (((1860345 585...
## 4 MULTIPOLYGON (((2049387 583...
## 5 MULTIPOLYGON (((2024489 567...
## 6 MULTIPOLYGON (((2024489 567...
## 7 MULTIPOLYGON (((1740438 571...
## 8 MULTIPOLYGON (((1866732 566...
## 9 MULTIPOLYGON (((1881590 548...
## 10 MULTIPOLYGON (((1557042 531...
Let’s try to plot the Land_area column. We might think that the following works, but it doesn’t!
#tm_shape(nz) +
# tm_fill(col = nz$Land_area)
Instead, tmap is expecting a character string naming the attribute associated with the geometry
tm_shape(nz) +
tm_fill(fill = "Land_area")
We can also add an argument that updates the title of the legend
tm_shape(nz) +
tm_fill(fill = "Land_area", title = "Area")
## Deprecated tmap v3 code detected. Code translated to v4
We can even make it more precise using the “expression” function
tm_shape(nz) +
tm_fill(fill = "Land_area", title = expression("Area (km"^2*")")) +
tm_borders()
## Deprecated tmap v3 code detected. Code translated to v4
Notice how the following maps display the same data, but look quite different
tm_shape(nz) +
tm_polygons(fill = "Median_income", style = "pretty")
## Deprecated tmap v3 code detected. Code translated to v4
tm_shape(nz) +
tm_polygons(fill = "Median_income", style = "equal")
## Deprecated tmap v3 code detected. Code translated to v4
tm_shape(nz) +
tm_polygons(fill = "Median_income", style = "quantile")
## Deprecated tmap v3 code detected. Code translated to v4
tm_shape(nz) +
tm_polygons(fill = "Median_income", style = "jenks")
## Deprecated tmap v3 code detected. Code translated to v4
We can also define custom bins
breaks = c(0, 3, 4, 5) * 10000
tm_shape(nz) +
tm_polygons(fill = "Median_income", breaks = breaks)
## Deprecated tmap v3 code detected. Code translated to v4
map_nz +
tm_shape(nz_elev) +
tm_raster(col_alpha = 0.7) +
tm_scale_continuous()
## SpatRaster object downsampled to 1141 by 877 cells.
map_nz +
tm_shape(nz) +
tm_polygons(fill = "Island")
To clearly give readers the context of our map, we can include a compass and scale bar
map_nz +
tm_compass(type = "4star", position = c("left", "top")) +
tm_scale_bar(breaks = c(0, 100, 200), text.size = 1)
## Warning: As of version 4.0, tm_scale_bar has been renamed to tm_scalebar and is
## therefore deprecated
Instead of using a compass and scale bar, we could add latitude/longitudes graticules
map_nz +
tm_graticules()
We can also update the background color
map_nz +
tm_graticules() +
tm_layout(bg.color = "lightblue")
urb_1970_2030 <- urban_agglomerations %>%
filter(year %in% c(1970, 1990, 2010, 2030))
tm_shape(world) +
tm_polygons() +
tm_shape(urb_1970_2030) +
tm_symbols(col = "black", border.col = "white", size = "population_millions") +
tm_facets(by = "year", nrow = 2, free.coords = FALSE)
## Deprecated tmap v3 code detected. Code translated to v4
tmap_mode("view")
## tmap mode set to 'view'
map_nz
To go back to regular plotting, we just need enter plotting mode
tmap_mode("plot")
## tmap mode set to 'plot'