tmap is a package for making thematic maps. In this Notebook, we’ll use tmap to make a map that includes the Yosemite:

  • park boundary
  • roads
  • cell towers
  • campgrounds

We’ll make two versions of the map - a traditional static map and an interactive map.

Import all the layers

First, import the park boundary, cell towers, and roads. At the same time, we’ll (re)project everything into UTM 11N WGS 84.

library(sf)
Linking to GEOS 3.9.0, GDAL 3.2.1, PROJ 7.2.1
library(dplyr)

Attaching package: 㤼㸱dplyr㤼㸲

The following objects are masked from 㤼㸱package:stats㤼㸲:

    filter, lag

The following objects are masked from 㤼㸱package:base㤼㸲:

    intersect, setdiff, setequal, union
epsg_utm11n_wgs84 <- 32611

## Park boundary
yose_bnd_utm <- st_read(dsn="./data", layer="yose_boundary") %>% 
  st_transform(epsg_utm11n_wgs84)
Reading layer `yose_boundary' from data source `D:\Workshops\R-Spatial\rspatial_mod\outputs\rspatial_data\data' using driver `ESRI Shapefile'
Simple feature collection with 1 feature and 11 fields
Geometry type: POLYGON
Dimension:     XY
Bounding box:  xmin: -119.8864 ymin: 37.4947 xmax: -119.1964 ymax: 38.18515
Geodetic CRS:  North_American_Datum_1983
## Roads
yose_roads_utm <- st_read("./data/yose_roads.gdb", "Yosemite_Roads") %>% 
  st_transform(epsg_utm11n_wgs84)
Reading layer `Yosemite_Roads' from data source `D:\Workshops\R-Spatial\rspatial_mod\outputs\rspatial_data\data\yose_roads.gdb' using driver `OpenFileGDB'
Simple feature collection with 823 features and 40 fields
Geometry type: MULTILINESTRING
Dimension:     XY
Bounding box:  xmin: 234658.1 ymin: 4139484 xmax: 324852.6 ymax: 4250252
Projected CRS: NAD83 / UTM zone 11N
## Cell towers
gdb_fn <- "./data/yose_communications.gdb"; file.exists(gdb_fn)  ## two commands separated by ;
[1] TRUE
yose_celltwrs_utm <- st_read(gdb_fn, "Cell_Towers") %>% 
  st_transform(epsg_utm11n_wgs84)
Reading layer `Cell_Towers' from data source `D:\Workshops\R-Spatial\rspatial_mod\outputs\rspatial_data\data\yose_communications.gdb' using driver `OpenFileGDB'
Simple feature collection with 5 features and 6 fields
Geometry type: POINT
Dimension:     XY
Bounding box:  xmin: 251532.4 ymin: 4158756 xmax: 293307.2 ymax: 4194328
Projected CRS: NAD83 / UTM zone 11N
## Campsites
yose_campgrounds_utm <- st_read(dsn="./data", layer="yose_poi") %>% 
  st_transform(epsg_utm11n_wgs84) %>% 
  filter(POITYPE == "Campground")
Reading layer `yose_poi' from data source `D:\Workshops\R-Spatial\rspatial_mod\outputs\rspatial_data\data' using driver `ESRI Shapefile'
Simple feature collection with 2720 features and 30 fields
Geometry type: POINT
Dimension:     XY
Bounding box:  xmin: 246416.2 ymin: 4153717 xmax: 301510.7 ymax: 4208419
Projected CRS: NAD83 / UTM zone 11N

CHALLENGE: How many cell towers & campgrounds

How many cell towers are there? How many campgrounds are there? Answer

# Your answer here

Map the Park Boundary

Let’s start with a simple map of just the park boundary:

library(tmap)
Registered S3 methods overwritten by 'htmltools':
  method               from         
  print.html           tools:rstudio
  print.shiny.tag      tools:rstudio
  print.shiny.tag.list tools:rstudio
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
tmap_mode("plot")
tmap mode set to plotting
tm_shape(yose_bnd_utm) + tm_polygons()

Now make the fill and outline dark green, the fill 20% transparent (alpha = 0), the border line a little thicker (lwd = 2):

tm_shape(yose_bnd_utm) + 
  tm_polygons(col = "darkgreen", alpha = 0.2, border.col = "darkgreen", lwd = 2)

Next, we’ll add a title by adding tm_layout() to our tmap object:

tm_shape(yose_bnd_utm) + 
  tm_polygons(col = "darkgreen", alpha = 0.2, border.col = "darkgreen", lwd = 2) +
tm_layout(main.title = "Yosemite NP Cell Towers")

CHALLENGE: Add a scale bar

Add a scale bar to the map. Hint: add tm_scale_bar() to the map. Answer

# Your answer here

Add the Roads and the Cell Towers

Next we’ll add the roads. This requires tacking on another tm_shape(), followed by a function that draws lines.

tm_shape(yose_bnd_utm) + 
  tm_polygons(col = "darkgreen", alpha = 0.2, border.col = "darkgreen", lwd = 2) +
tm_shape(yose_roads_utm) +
  tm_lines(col = "gray50")

In a similar fashion, we’ll add the cell towers as little blue dots:

tm_shape(yose_bnd_utm) + 
  tm_polygons(col = "darkgreen", alpha = 0.2, border.col = "darkgreen", lwd = 2) +
tm_shape(yose_roads_utm) +
  tm_lines(col = "gray50") +
tm_shape(yose_celltwrs_utm) +
  tm_symbols(col = "blue", size = 0.5)

CHALLENGE: Add the campgrounds

Add the campgrounds to the map as little red dots. Hint: you can render point layers with tm_symbols() or tm_dots(). Answer

# Your answer here

Make an interactive map

We can switch to ‘interactive map mode’ by running tmap_mode():

tmap_mode("view")
tmap mode set to interactive viewing
## tmap_mode("plot")  # go back to plot mode

Now that we’re in ‘view’ mode, tmap objects be rendered as little interactive maps. We can ‘redraw’ the last tmap object using tmap_last():

tmap_last()

Switch-out the basemap:

tm_shape(yose_bnd_utm %>% st_geometry()) + 
  tm_polygons(col = "darkgreen", alpha = 0.2, border.col = "darkgreen", lwd = 2) +
tm_shape(yose_roads_utm %>% st_geometry()) +
  tm_lines(col = "gray50") +
tm_shape(yose_celltwrs_utm %>% st_geometry()) +
  tm_symbols(col = "blue", size = 0.5) +
tm_shape(yose_campgrounds_utm %>% st_geometry()) +
  tm_symbols(col = "red", size = 0.5) +
  tm_basemap("Esri.WorldTopoMap")

Configure Pop-ups

Lastly we’ll disable interactivity (i.e., hover-over text and popup windows) on all layers except for the campgrounds:

tm_shape(yose_bnd_utm %>% st_geometry()) + 
  tm_polygons(col = "darkgreen", alpha = 0.2, border.col = "darkgreen", lwd = 2, interactive = FALSE) +
tm_shape(yose_roads_utm %>% st_geometry()) +
  tm_lines(col = "gray50", interactive = FALSE) +
tm_shape(yose_celltwrs_utm %>% st_geometry()) +
  tm_symbols(col = "blue", size = 0.5, interactive = FALSE) +
tm_shape(yose_campgrounds_utm %>% select(POINAME)) +
  tm_symbols(col = "red", size = 0.5, id = "POINAME") +
  tm_basemap("Esri.WorldTopoMap")

Tip: for more control over pop-ups, use leaflet.

End

Congratulations, you have completed the Notebook!

To view your Notebook at HTML, save it (again), then click the ‘Preview’ button in the RStudio toolbar. If

LS0tDQp0aXRsZTogIk1ha2UgYSBNYXAgb2YgWW9zZW1pdGUiDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCi0tLQ0KDQpgdG1hcGAgaXMgYSBwYWNrYWdlIGZvciBtYWtpbmcgdGhlbWF0aWMgbWFwcy4gSW4gdGhpcyBOb3RlYm9vaywgd2UnbGwgdXNlIGB0bWFwYCB0byBtYWtlIGEgbWFwIHRoYXQgaW5jbHVkZXMgdGhlIFlvc2VtaXRlOg0KDQotIHBhcmsgYm91bmRhcnkgIA0KLSByb2FkcyAgDQotIGNlbGwgdG93ZXJzICANCi0gY2FtcGdyb3VuZHMNCg0KV2UnbGwgbWFrZSB0d28gdmVyc2lvbnMgb2YgdGhlIG1hcCAtIGEgdHJhZGl0aW9uYWwgc3RhdGljIG1hcCBhbmQgYW4gaW50ZXJhY3RpdmUgbWFwLg0KDQojIyBJbXBvcnQgYWxsIHRoZSBsYXllcnMNCg0KRmlyc3QsIGltcG9ydCB0aGUgcGFyayBib3VuZGFyeSwgY2VsbCB0b3dlcnMsIGFuZCByb2Fkcy4gQXQgdGhlIHNhbWUgdGltZSwgd2UnbGwgKHJlKXByb2plY3QgZXZlcnl0aGluZyBpbnRvIFVUTSAxMU4gV0dTIDg0Lg0KDQpgYGB7ciBjaHVuazAxfQ0KbGlicmFyeShzZikNCmxpYnJhcnkoZHBseXIpDQoNCmVwc2dfdXRtMTFuX3dnczg0IDwtIDMyNjExDQoNCiMjIFBhcmsgYm91bmRhcnkNCnlvc2VfYm5kX3V0bSA8LSBzdF9yZWFkKGRzbj0iLi9kYXRhIiwgbGF5ZXI9Inlvc2VfYm91bmRhcnkiKSAlPiUgDQogIHN0X3RyYW5zZm9ybShlcHNnX3V0bTExbl93Z3M4NCkNCg0KIyMgUm9hZHMNCnlvc2Vfcm9hZHNfdXRtIDwtIHN0X3JlYWQoIi4vZGF0YS95b3NlX3JvYWRzLmdkYiIsICJZb3NlbWl0ZV9Sb2FkcyIpICU+JSANCiAgc3RfdHJhbnNmb3JtKGVwc2dfdXRtMTFuX3dnczg0KQ0KDQojIyBDZWxsIHRvd2Vycw0KZ2RiX2ZuIDwtICIuL2RhdGEveW9zZV9jb21tdW5pY2F0aW9ucy5nZGIiOyBmaWxlLmV4aXN0cyhnZGJfZm4pICAjIyB0d28gY29tbWFuZHMgc2VwYXJhdGVkIGJ5IDsNCnlvc2VfY2VsbHR3cnNfdXRtIDwtIHN0X3JlYWQoZ2RiX2ZuLCAiQ2VsbF9Ub3dlcnMiKSAlPiUgDQogIHN0X3RyYW5zZm9ybShlcHNnX3V0bTExbl93Z3M4NCkNCg0KIyMgQ2FtcHNpdGVzDQp5b3NlX2NhbXBncm91bmRzX3V0bSA8LSBzdF9yZWFkKGRzbj0iLi9kYXRhIiwgbGF5ZXI9Inlvc2VfcG9pIikgJT4lIA0KICBzdF90cmFuc2Zvcm0oZXBzZ191dG0xMW5fd2dzODQpICU+JSANCiAgZmlsdGVyKFBPSVRZUEUgPT0gIkNhbXBncm91bmQiKQ0KYGBgDQoNCiMjIENIQUxMRU5HRTogSG93IG1hbnkgY2VsbCB0b3dlcnMgJiBjYW1wZ3JvdW5kcw0KDQpIb3cgbWFueSBjZWxsIHRvd2VycyBhcmUgdGhlcmU/IEhvdyBtYW55IGNhbXBncm91bmRzIGFyZSB0aGVyZT8gW0Fuc3dlcl0oaHR0cHM6Ly9iaXQubHkvM2t5Rk1PVCkNCg0KYGBge3IgY2h1bmswMn0NCiMgWW91ciBhbnN3ZXIgaGVyZQ0KDQpgYGANCg0KIyMgTWFwIHRoZSBQYXJrIEJvdW5kYXJ5DQoNCkxldCdzIHN0YXJ0IHdpdGggYSBzaW1wbGUgbWFwIG9mIGp1c3QgdGhlIHBhcmsgYm91bmRhcnk6DQoNCmBgYHtyIGNodW5rMDN9DQpsaWJyYXJ5KHRtYXApDQp0bWFwX21vZGUoInBsb3QiKQ0KDQp0bV9zaGFwZSh5b3NlX2JuZF91dG0pICsgdG1fcG9seWdvbnMoKQ0KYGBgDQoNCk5vdyBtYWtlIHRoZSBmaWxsIGFuZCBvdXRsaW5lIGRhcmsgZ3JlZW4sIHRoZSBmaWxsIDIwJSB0cmFuc3BhcmVudCAoYWxwaGEgPSAwKSwgdGhlIGJvcmRlciBsaW5lIGEgbGl0dGxlIHRoaWNrZXIgKGx3ZCA9IDIpOg0KDQpgYGB7ciBjaHVuazA0fQ0KdG1fc2hhcGUoeW9zZV9ibmRfdXRtKSArIA0KICB0bV9wb2x5Z29ucyhjb2wgPSAiZGFya2dyZWVuIiwgYWxwaGEgPSAwLjIsIGJvcmRlci5jb2wgPSAiZGFya2dyZWVuIiwgbHdkID0gMikNCmBgYA0KDQpOZXh0LCB3ZSdsbCBhZGQgYSB0aXRsZSBieSBhZGRpbmcgYHRtX2xheW91dCgpYCB0byBvdXIgdG1hcCBvYmplY3Q6DQoNCmBgYHtyIGNodW5rMDV9DQp0bV9zaGFwZSh5b3NlX2JuZF91dG0pICsgDQogIHRtX3BvbHlnb25zKGNvbCA9ICJkYXJrZ3JlZW4iLCBhbHBoYSA9IDAuMiwgYm9yZGVyLmNvbCA9ICJkYXJrZ3JlZW4iLCBsd2QgPSAyKSArDQp0bV9sYXlvdXQobWFpbi50aXRsZSA9ICJZb3NlbWl0ZSBOUCBDZWxsIFRvd2VycyIpDQpgYGANCg0KIyMgQ0hBTExFTkdFOiBBZGQgYSBzY2FsZSBiYXINCg0KQWRkIGEgc2NhbGUgYmFyIHRvIHRoZSBtYXAuIEhpbnQ6IGFkZCBgdG1fc2NhbGVfYmFyKClgIHRvIHRoZSBtYXAuIFtBbnN3ZXJdKGh0dHBzOi8vYml0Lmx5LzNoV21EVnYpDQoNCmBgYHtyIGNodW5rMDZ9DQojIFlvdXIgYW5zd2VyIGhlcmUNCg0KYGBgDQoNCiMjIEFkZCB0aGUgUm9hZHMgYW5kIHRoZSBDZWxsIFRvd2Vycw0KDQpOZXh0IHdlJ2xsIGFkZCB0aGUgcm9hZHMuIFRoaXMgcmVxdWlyZXMgdGFja2luZyBvbiBhbm90aGVyIGB0bV9zaGFwZSgpYCwgZm9sbG93ZWQgYnkgYSBmdW5jdGlvbiB0aGF0IGRyYXdzIGxpbmVzLg0KDQpgYGB7ciBjaHVuazA3fQ0KdG1fc2hhcGUoeW9zZV9ibmRfdXRtKSArIA0KICB0bV9wb2x5Z29ucyhjb2wgPSAiZGFya2dyZWVuIiwgYWxwaGEgPSAwLjIsIGJvcmRlci5jb2wgPSAiZGFya2dyZWVuIiwgbHdkID0gMikgKw0KdG1fc2hhcGUoeW9zZV9yb2Fkc191dG0pICsNCiAgdG1fbGluZXMoY29sID0gImdyYXk1MCIpDQpgYGANCg0KSW4gYSBzaW1pbGFyIGZhc2hpb24sIHdlJ2xsIGFkZCB0aGUgY2VsbCB0b3dlcnMgYXMgbGl0dGxlIGJsdWUgZG90czoNCg0KYGBge3IgY2h1bmswOH0NCnRtX3NoYXBlKHlvc2VfYm5kX3V0bSkgKyANCiAgdG1fcG9seWdvbnMoY29sID0gImRhcmtncmVlbiIsIGFscGhhID0gMC4yLCBib3JkZXIuY29sID0gImRhcmtncmVlbiIsIGx3ZCA9IDIpICsNCnRtX3NoYXBlKHlvc2Vfcm9hZHNfdXRtKSArDQogIHRtX2xpbmVzKGNvbCA9ICJncmF5NTAiKSArDQp0bV9zaGFwZSh5b3NlX2NlbGx0d3JzX3V0bSkgKw0KICB0bV9zeW1ib2xzKGNvbCA9ICJibHVlIiwgc2l6ZSA9IDAuNSkNCmBgYA0KDQojIyBDSEFMTEVOR0U6IEFkZCB0aGUgY2FtcGdyb3VuZHMgDQoNCkFkZCB0aGUgY2FtcGdyb3VuZHMgdG8gdGhlIG1hcCBhcyBsaXR0bGUgcmVkIGRvdHMuIEhpbnQ6IHlvdSBjYW4gcmVuZGVyIHBvaW50IGxheWVycyB3aXRoIGB0bV9zeW1ib2xzKClgIG9yIGB0bV9kb3RzKClgLiBbQW5zd2VyXShodHRwczovL2JpdC5seS8zaFFqdmREKQ0KDQpgYGB7ciBjaHVuazA5fQ0KIyBZb3VyIGFuc3dlciBoZXJlDQoNCmBgYA0KDQojIyBNYWtlIGFuIGludGVyYWN0aXZlIG1hcA0KDQpXZSBjYW4gc3dpdGNoIHRvICdpbnRlcmFjdGl2ZSBtYXAgbW9kZScgYnkgcnVubmluZyBgdG1hcF9tb2RlKClgOg0KDQpgYGB7ciBjaHVuazEwfQ0KdG1hcF9tb2RlKCJ2aWV3IikNCg0KIyMgdG1hcF9tb2RlKCJwbG90IikgICMgZ28gYmFjayB0byBwbG90IG1vZGUNCmBgYA0KDQpOb3cgdGhhdCB3ZSdyZSBpbiAndmlldycgbW9kZSwgdG1hcCBvYmplY3RzIGJlIHJlbmRlcmVkIGFzIGxpdHRsZSBpbnRlcmFjdGl2ZSBtYXBzLiBXZSBjYW4gJ3JlZHJhdycgdGhlIGxhc3QgdG1hcCBvYmplY3QgdXNpbmcgYHRtYXBfbGFzdCgpYDoNCg0KYGBge3IgY2h1bmsxMX0NCnRtYXBfbGFzdCgpDQpgYGANCg0KU3dpdGNoLW91dCB0aGUgYmFzZW1hcDoNCg0KYGBge3IgY2h1bmsxMn0NCnRtX3NoYXBlKHlvc2VfYm5kX3V0bSAlPiUgc3RfZ2VvbWV0cnkoKSkgKyANCiAgdG1fcG9seWdvbnMoY29sID0gImRhcmtncmVlbiIsIGFscGhhID0gMC4yLCBib3JkZXIuY29sID0gImRhcmtncmVlbiIsIGx3ZCA9IDIpICsNCnRtX3NoYXBlKHlvc2Vfcm9hZHNfdXRtICU+JSBzdF9nZW9tZXRyeSgpKSArDQogIHRtX2xpbmVzKGNvbCA9ICJncmF5NTAiKSArDQp0bV9zaGFwZSh5b3NlX2NlbGx0d3JzX3V0bSAlPiUgc3RfZ2VvbWV0cnkoKSkgKw0KICB0bV9zeW1ib2xzKGNvbCA9ICJibHVlIiwgc2l6ZSA9IDAuNSkgKw0KdG1fc2hhcGUoeW9zZV9jYW1wZ3JvdW5kc191dG0gJT4lIHN0X2dlb21ldHJ5KCkpICsNCiAgdG1fc3ltYm9scyhjb2wgPSAicmVkIiwgc2l6ZSA9IDAuNSkgKw0KICB0bV9iYXNlbWFwKCJFc3JpLldvcmxkVG9wb01hcCIpDQpgYGANCg0KIyMgQ29uZmlndXJlIFBvcC11cHMNCg0KTGFzdGx5IHdlJ2xsIGRpc2FibGUgaW50ZXJhY3Rpdml0eSAoaS5lLiwgaG92ZXItb3ZlciB0ZXh0IGFuZCBwb3B1cCB3aW5kb3dzKSBvbiBhbGwgbGF5ZXJzIGV4Y2VwdCBmb3IgdGhlIGNhbXBncm91bmRzOiANCg0KYGBge3IgY2h1bmsxM30NCnRtX3NoYXBlKHlvc2VfYm5kX3V0bSAlPiUgc3RfZ2VvbWV0cnkoKSkgKyANCiAgdG1fcG9seWdvbnMoY29sID0gImRhcmtncmVlbiIsIGFscGhhID0gMC4yLCBib3JkZXIuY29sID0gImRhcmtncmVlbiIsIGx3ZCA9IDIsIGludGVyYWN0aXZlID0gRkFMU0UpICsNCnRtX3NoYXBlKHlvc2Vfcm9hZHNfdXRtICU+JSBzdF9nZW9tZXRyeSgpKSArDQogIHRtX2xpbmVzKGNvbCA9ICJncmF5NTAiLCBpbnRlcmFjdGl2ZSA9IEZBTFNFKSArDQp0bV9zaGFwZSh5b3NlX2NlbGx0d3JzX3V0bSAlPiUgc3RfZ2VvbWV0cnkoKSkgKw0KICB0bV9zeW1ib2xzKGNvbCA9ICJibHVlIiwgc2l6ZSA9IDAuNSwgaW50ZXJhY3RpdmUgPSBGQUxTRSkgKw0KdG1fc2hhcGUoeW9zZV9jYW1wZ3JvdW5kc191dG0gJT4lIHNlbGVjdChQT0lOQU1FKSkgKw0KICB0bV9zeW1ib2xzKGNvbCA9ICJyZWQiLCBzaXplID0gMC41LCBpZCA9ICJQT0lOQU1FIikgKw0KICB0bV9iYXNlbWFwKCJFc3JpLldvcmxkVG9wb01hcCIpDQpgYGANCg0KVGlwOiBmb3IgbW9yZSBjb250cm9sIG92ZXIgcG9wLXVwcywgdXNlIGxlYWZsZXQuDQoNCiMjIEVuZA0KDQpDb25ncmF0dWxhdGlvbnMsIHlvdSBoYXZlIGNvbXBsZXRlZCB0aGUgTm90ZWJvb2shIA0KDQpUbyB2aWV3IHlvdXIgTm90ZWJvb2sgYXQgSFRNTCwgc2F2ZSBpdCAoYWdhaW4pLCB0aGVuIGNsaWNrIHRoZSAnUHJldmlldycgYnV0dG9uIGluIHRoZSBSU3R1ZGlvIHRvb2xiYXIuIElmDQoNCg0K