+ - 0:00:00
Notes for current slide
Notes for next slide

Visualizing Spatial Data

(static and interactive maps)

1 / 94

R has great map-making functionality!

2 / 94

This map was created in R

3 / 94

This map was created in R

4 / 94

This map was created in R

5 / 94

What packages should you use?

6 / 94

There are dozens of mapping-related packages in R

7 / 94

There are dozens of mapping-related packages in R

  • But only a few are all-purpose
7 / 94

All-purpose static mapping

  • The plot() function
  • {tmap}
  • {ggplot2} (we won't cover {ggplot2})
8 / 94

All-purpose interactive mapping

  • {tmap}
  • {mapview}
  • {leaflet} (we won't cover {leaflet})
9 / 94

A lot of great packages for niche mapping needs

  • {rayshader}
  • {geogrid}
  • {globe}
  • {linemap}
  • {cartogram}
  • {cartography}
  • {mapedit}
  • {rasterVis}
10 / 94

Static mapping

11 / 94

Take home messages

12 / 94

Take home messages

  • I use plot() for a quick look at data
12 / 94

Take home messages

  • I use plot() for a quick look at data

  • I use {tmap} for everything else

12 / 94

Take home messages

  • I use plot() for a quick look at data

  • I use {tmap} for everything else

  • {tmap} has an insane amount of customization allowed, we will only touch the surface

12 / 94

Why not ggplot2?

13 / 94

Why not ggplot2?

  • I love ggplot2 and use it every day
13 / 94

Why not ggplot2?

  • I love ggplot2 and use it every day

  • But I find making maps significantly easier in tmap

    • Can do almost anything in tmap
    • Easy to include just fill, just borders, etc
    • Interactive views
    • etc...
13 / 94

But I will show a ggplot-map at the end of this section

14 / 94

plot()

15 / 94

Yes plot() is not super exciting

16 / 94

But plot() is great for a quick look at your data

17 / 94

plot() has methods for vector and raster data

18 / 94

plot() has methods for vector and raster data

The packages need to be loaded to plot vector and raster data

18 / 94

Some setup: load packages

No need to type with me, you'll practice in the exercise

library(sf) # read vectors
library(raster) # read rasters
library(tmap) # mapping
19 / 94

Some setup: read in NYC data

boroughs <- read_sf("boroughs.gpkg")
schools <- read_sf("schools.shp")
canopy <- raster("canopy.grd")
20 / 94

With vectors the default is to plot the attributes

plot(boroughs)
21 / 94

With vectors the default is to plot the attributes

plot(boroughs)
21 / 94

I don't really like this default

22 / 94

You can plot a single attribute

23 / 94

You can plot a single attribute

plot(boroughs['Shape_Area'], main = "Area",
pal = rev(heat.colors(5)))
23 / 94

For a quick look at vectors, I often just want the geometry

24 / 94

For a quick look at vectors, I often just want the geometry

  • You can extract just the geometry with st_geometry()
24 / 94

For a quick look at vectors, I often just want the geometry

  • You can extract just the geometry with st_geometry()

  • Then call plot() on the output

24 / 94

st_geometry() and then plot

st_geometry(boroughs) %>% plot()
25 / 94

Or wrap the two functions

plot(st_geometry(boroughs))
26 / 94

Try to memorize this concept/code

st_geometry(boroughs) %>% plot()
plot(st_geometry(boroughs))
27 / 94

To combine layers with plot() use add = TRUE

plot(st_geometry(boroughs))
plot(st_geometry(schools), add = TRUE,
pch = 16, col = "red", cex = 0.5)
28 / 94

Careful with add = TRUE, only works with st_geometry()

29 / 94

Careful with add = TRUE, only works with st_geometry()

# This won't work!
plot(boroughs)
plot(schools, add = TRUE)

29 / 94

Easy to use plot() with rasters

plot(canopy) # a single band raster
30 / 94

If your raster has multiple layers (like an image) ...

plot() maps each layer separately

plot(manhattan)
31 / 94

If your raster has multiple layers (like an image) ...

plot() maps each layer separately

plot(manhattan)
31 / 94

If your raster has a red, green and blue layer (like an image)

You can plot them together...

32 / 94

If your raster has a red, green and blue layer (like an image)

You can plot them together...

plotRGB(manhattan)
32 / 94

Combine rasters and vectors with plot()

33 / 94

Combine rasters and vectors with plot()

plot(canopy)
plot(st_geometry(schools), add = T,
pch = 16, col = "red", cex = 0.5)
33 / 94

For more sophisticated and fun static maps I use {tmap}

34 / 94

{tmap}

35 / 94

So much control with {tmap}!

36 / 94

So much control with {tmap}!

tm_text(text, size = 1, col = NA, root = 3, clustering = FALSE,
size.lim = NA, sizes.legend = NULL, sizes.legend.labels = NULL,
sizes.legend.text = "Abc", n = 5, style = ifelse(is.null(breaks),
"pretty", "fixed"), breaks = NULL, interval.closure = "left",
palette = NULL, labels = NULL, labels.text = NA, midpoint = NULL,
stretch.palette = TRUE, contrast = NA, colorNA = NA,
textNA = "Missing", showNA = NA, colorNULL = NA, fontface = NA,
fontfamily = NA, alpha = NA, case = NA, shadow = FALSE,
bg.color = NA, bg.alpha = NA, size.lowerbound = 0.4,
print.tiny = FALSE, scale = 1, auto.placement = FALSE,
remove.overlap = FALSE, along.lines = FALSE,
overwrite.lines = FALSE, just = "center", xmod = 0, ymod = 0,
title.size = NA, title.col = NA, legend.size.show = TRUE,
legend.col.show = TRUE, legend.format = list(),
legend.size.is.portrait = FALSE, legend.col.is.portrait = TRUE,
legend.size.reverse = FALSE, legend.col.reverse = FALSE,
legend.hist = FALSE, legend.hist.title = NA, legend.size.z = NA,
legend.col.z = NA, legend.hist.z = NA, group = NA,
auto.palette.mapping = NULL, max.categories = NULL)
36 / 94

{tmap} syntax is similar to {ggplot2}

# data set up layer
tm_shape(boroughs) + tm_polygons()
37 / 94

{tmap} syntax is similar to {ggplot2}

# data set up layer
tm_shape(boroughs) + tm_polygons()
37 / 94

A short-cut qtm()

Instead of plot() I often use this

qtm(boroughs)
38 / 94

Add multiple layers based on one input

tm_shape(boroughs) +
tm_polygons() +
tm_dots(size = 2) +
tm_text("BoroName", col = "red", size = 1.5)
39 / 94

Add multiple layers based on one input

tm_shape(boroughs) +
tm_polygons() +
tm_dots(size = 2) +
tm_text("BoroName", col = "red", size = 1.5)
39 / 94

Or multiple different layers using multiple shapes

40 / 94

Or multiple different layers using multiple shapes

tm_shape(boroughs) + tm_borders() +
tm_shape(schools) + tm_dots(size = 0.25)
40 / 94

You can also save parts of the map and reuse

mymap <- tm_shape(boroughs) + tm_polygons()
41 / 94

You can also save parts of the map and reuse

mymap <- tm_shape(boroughs) + tm_polygons()
mymap + tm_dots(size = 2) +
tm_text("BoroName", col = "red")
41 / 94

Choropleth (color-coded map) based on a variable. So easy!

tm_shape(boroughs) + tm_polygons("Shape_Area")
42 / 94

Choropleth (color-coded map) based on a variable. So easy!

tm_shape(boroughs) + tm_polygons("Shape_Area")
42 / 94

Or show an attribute with tm_symbols()

tm_shape(boroughs) + tm_borders() +
tm_symbols("Shape_Area", scale = 2)
43 / 94

Plot multiple variables at once

tm_shape(boroughs) + tm_polygons(c("Shape_Area", "BoroName"))
44 / 94

tm_shape() can accept vector or raster

45 / 94

Single-band raster with tm_raster()

tm_shape(canopy) + tm_raster()
46 / 94

Single-band raster with tm_raster()

tm_shape(canopy) + tm_raster()
46 / 94

A multi-layer raster with tm_rgb()

tm_shape(manhattan) + tm_rgb()
47 / 94

A multi-layer raster with tm_rgb()

tm_shape(manhattan) + tm_rgb()
47 / 94

Vector and raster

tm_shape(manhattan) + tm_rgb()+
tm_shape(boroughs) + tm_borders(col = "white", lwd = 2)
48 / 94

Vector and raster

tm_shape(manhattan) + tm_rgb()+
tm_shape(boroughs) + tm_borders(col = "white", lwd = 2)
48 / 94

Include a basemap in your map

Use a function from the companion package, {tmaptools}

49 / 94

Include a basemap in your map

Use a function from the companion package, {tmaptools}

osmtiles <- tmaptools::read_osm(boroughs,
type="stamen-terrain")
49 / 94

Include a basemap in your map

tm_shape(osmtiles) + tm_raster() +
tm_shape(boroughs) +
tm_borders(lwd = 2, col = "yellow")
50 / 94

Map extent is driven by the "master"

  • First shape is master by default
51 / 94

Map extent is driven by the "master"

  • First shape is master by default

  • in tm_shape() can use is.master = TRUE

51 / 94

Here is the default (extent based on raster)

tm_shape(canopy) +
tm_raster(title = "(percent canopy)", alpha = 0.75) +
tm_shape(boroughs) + tm_borders(lwd = 2, col = "blue")
52 / 94

Force the extent to be the polygon borders

tm_shape(canopy) +
tm_raster(title = "(percent canopy)", alpha = 0.75) +
tm_shape(boroughs, is.master = TRUE) + tm_borders(lwd = 2, col = "blue")
53 / 94

Force the extent to be the polygon borders

tm_shape(canopy) +
tm_raster(title = "(percent canopy)", alpha = 0.75) +
tm_shape(boroughs, is.master = TRUE) + tm_borders(lwd = 2, col = "blue")
53 / 94

Using color palettes in tmap

54 / 94

palette_explorer() is great

tmaptools::palette_explorer()
55 / 94

Use a palette with the pal argument

tm_shape(neighborhoods) +
tm_polygons("shape_area", n = 5, pal = "Greens")
56 / 94

Use a palette with the pal argument

tm_shape(neighborhoods) +
tm_polygons("shape_area", n = 5, pal = "Greens")
56 / 94

Use - to reverse the palette

tm_shape(neighborhoods) +
tm_polygons("shape_area", n = 5, pal = "-Greens")
57 / 94

Use - to reverse the palette

tm_shape(neighborhoods) +
tm_polygons("shape_area", n = 5, pal = "-Greens")
57 / 94

Alter the map layout with tm_layout()

58 / 94

Alter the map layout with tm_layout()

tm_shape(neighborhoods) +
tm_polygons("shape_area", n = 5, pal = "Greens") +
tm_layout(legend.show = FALSE, frame = FALSE)
58 / 94

Save your maps with tmap_save()

59 / 94

Save your maps with tmap_save()

mymap <- tm_shape(boroughs) + tm_polygons()
tmap_save(mymap, "mymap.png")
59 / 94

It's easy to include more than one map in an image with tmap_arrange()

60 / 94

It's easy to include more than one map in an image with tmap_arrange()

# Create three maps
m1 <- tm_shape(boroughs) + tm_polygons()
m2 <- tm_shape(neighborhoods) + tm_polygons()
m3 <- tm_shape(schools) + tm_dots(size = 0.25)
60 / 94

Arrange them on one image

61 / 94

Arrange them on one image

tmap_arrange(m1, m2, m3, nrow = 1)
61 / 94

Arrange them on one image

tmap_arrange(m1, m2, m3, nrow = 1)

61 / 94

So many great other functions to explore

  • tmap_save()
  • tm_layout()
  • tm_style()
  • tm_facets()
  • tm_animation()
  • tm_scale_bar()
  • tm_compass()
62 / 94

As promised earlier, three slides on mapping with {ggplot2}

63 / 94

{ggplot2} has a special layer for {sf} objects

64 / 94

{ggplot2} has a special layer for {sf} objects

  • geom_sf()
64 / 94

With geom_sf() no need to specify x and y

  • Unlike geom_line(), geom_points() etc
65 / 94

To create a choropleth use aes() with the fill argument

66 / 94

To create a choropleth use aes() with the fill argument

library(ggplot2)
ggplot() +
geom_sf(data = boroughs, aes(fill = BoroCode)) +
geom_sf(data = schools, color = "purple")

66 / 94

You can also make nice maps with {ggplot2}

67 / 94

Keep in mind, there are other packages worth exploring

68 / 94

Quick example of geogrid

69 / 94

Hillshading with rayshader

70 / 94

Cartographic representations with {cartography}

71 / 94

open_exercise(3) and work on activity 1-9 then stop

72 / 94

Interactive maps

73 / 94

There are two packages I use for interactive maps

  • {mapview} (for a quick interactive look)
  • {tmap} (for a more polished interactive map)
74 / 94

Why not RStudio's {leaflet}

  • Main reason is it requires layers to be unprojected (we will discuss)

  • There are work-arounds like leafletCRS()

  • But {tmap} and {mapview} do a great job

75 / 94

Both {tmap} and {mapview} also use the Leaflet JavaScript API

76 / 94

Since we're already talking about {tmap} let's start with {tmap}

77 / 94

Remember this static {tmap} from earlier?

78 / 94

Use tmap_mode() to change from static to interactive

79 / 94

Use tmap_mode() to change from static to interactive

tmap_mode("plot") # default
my_map
79 / 94

So easy to make it interactive

80 / 94

So easy to make it interactive

tmap_mode("view") # make interactive
my_map # recreate plot
80 / 94

Running tmap_mode() with no argument will give the current mode

81 / 94

Running tmap_mode() with no argument will give the current mode

tmap_mode()
# current tmap mode is "view"
81 / 94

tmap can do side-by-side linked plots

82 / 94

tmap can do side-by-side linked plots

tmap_mode("view")
tm_shape(boroughs) +
tm_polygons(c("pop2018", "pop_change"),
palette = "Oranges")
82 / 94

Save your interactive tmap with tmap_save()

mymap <- tm_shape(boroughs) + tm_polygons()
tmap_save(mymap, "mymap.html")
83 / 94

Save your interactive tmap with tmap_save()

mymap <- tm_shape(boroughs) + tm_polygons()
tmap_save(mymap, "mymap.html")
83 / 94

{mapview}

84 / 94

Great for a quick interactive look at data

85 / 94

Great for a quick interactive look at data

library(mapview)
mapview(boroughs)
85 / 94

Like {tmap}, a lot of customization allowed

mapview(x, map = NULL,
maxpixels = mapviewGetOption("mapview.maxpixels"),
col.regions = mapviewGetOption("raster.palette")(256), at = NULL,
na.color = mapviewGetOption("na.color"), use.layer.names = FALSE,
values = NULL, map.types = mapviewGetOption("basemaps"),
alpha.regions = 0.8, legend = mapviewGetOption("legend"),
legend.opacity = 1, trim = TRUE,
verbose = mapviewGetOption("verbose"), layer.name = NULL,
homebutton = TRUE, native.crs = FALSE, method = c("bilinear",
"ngb"), label = TRUE, query.type = c("mousemove", "click"),
query.digits, query.position = "topright", query.prefix = "Layer",
viewer.suppress = FALSE, ...)
86 / 94

And easier than...

tmap_mode("view")
tm_shape(boroughs) + tm_polygons()
87 / 94

Multiple layers in one map with list()

88 / 94

Multiple layers in one map with list()

library(mapview)
mapview(list(boroughs, schools))
88 / 94

Alternative syntax for multiple layers

89 / 94

Alternative syntax for multiple layers

mapview(boroughs) + mapview(schools)
89 / 94

Alternative syntax for multiple layers

mapview(boroughs) + mapview(schools)
mapview(boroughs) + schools
89 / 94

Color-code based on an attribute use the zcol argument

mapview(boroughs, zcol = "Shape_Area")
90 / 94

Also allows rasters

91 / 94

Also allows rasters

mapview(canopy, alpha.regions = 0.4)
91 / 94

Saving your mapview interactive map with mapshot

Output is very similar to {tmap} (html file and folder)

92 / 94

Saving your mapview interactive map with mapshot

Output is very similar to {tmap} (html file and folder)

mymap <- mapview(boroughs)
mapshot(mymap, "mymap.html")
92 / 94

For both static and interactive maps

93 / 94

For both static and interactive maps

  • You can include in R markdown
93 / 94

For both static and interactive maps

  • You can include in R markdown

  • You can include in shiny application

93 / 94

For both static and interactive maps

  • You can include in R markdown

  • You can include in shiny application

  • If you save with tmap_save() or mapshot() you can upload the files directly to a server

93 / 94

open_exercise(3) and finish

94 / 94

R has great map-making functionality!

2 / 94
Paused

Help

Keyboard shortcuts

, , Pg Up, k Go to previous slide
, , Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
Esc Back to slideshow