m <- leaflet() |>
addTiles() |> # Add default OpenStreetMap map tiles
addMarkers(lng=-63.5932, lat=44.63697, popup="Math & Stats, Dalhousie U")
m # Print the map
28 Mapping II
Many online services generate tile maps. Generally a small number of maps are available for free and then further maps require a subscription. For causal use the free service tier is almost always sufficient. To keep track of your usage you sometimes need to sign up for an API key. The first example below is unusual because you can use these maps without any account. Tools and services for this sort of mapping change frequently, so this lesson shows how to use two different services.
28.1 Tiled maps with leaflet
In the previous lesson we made maps to show geographical data using map outlines from R packages. In this lesson we will look at making maps that build on detailed basemaps from online mapping systems. Google maps is a well known service; OpenStreetMap is a community-built free alternative. We will use the leaflet
package.
Let’s make a map and place a marker at the location of the Mathematics and Statistics Department. You can pan and zoom this map from within Rstudio and in the knitted output.
If you want to connect a name to a location, you can use the getbb
function from osmdata
(OpenStreetMap data). This gives the bounding box (upper left and lower right latitude and longitude coordinates):
getbb('halifax')
min max
x -63.72266 -63.54275
y 44.58117 44.71121
Let’s use the city database we used in the MDS lesson to label the 61 cities we selected in that lesson.
cities <- read_csv("static/selected_cities.csv", show_col_types = FALSE)
m2 <- leaflet(data = cities) |>
addTiles() |>
addCircleMarkers(~ lng, ~lat, label = ~city)
m2
There are several different basemaps, or tiles, that you can use. A fun one to look at – because it changes frequently is a radar map for the USA from Iowa State.
m3 <- leaflet(data = cities) |>
addTiles() |>
addCircleMarkers(~ lng, ~lat, label = ~city) %>%
addWMSTiles("http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi",
layers = "nexrad-n0r-900913",
options = WMSTileOptions(format = "image/png", transparent = TRUE),
attribution = "Weather data © 2012 IEM Nexrad") |>
setView(-93.65, 42.0285, zoom = 4)
m3
It’s common to see “chloropleth” maps of the USA in which geographic regions are coloured to show a quantitative or categorical variable, such as population density or election results. These maps are less common in Canada due to two main factors: the geographic concentration of the population in cities means that area maps are even less informative than for the USA and the latitude range of Canada makes for some severe challenges when plotting whole-country chloropleth maps on commonly used projections. Nevertheless, it is possible. Here’s a demonstration with some random numbers for “data”.
library(geojsonio)
pal <- colorNumeric("viridis", NULL) # make a viridis palette
canada <- geojson_read("https://gist.githubusercontent.com/mikelotis/2156d7c170d10d2c77cb79424fe2137d/raw/7a13748ed7ea5ba64876c77c53b6cb64dd5c3ab0/canada-province.geojson", what="sp")
my_values = runif(13, 0, 10) # random numbers between 0 and 10
leaflet() |>
addTiles() |>
addPolygons(data = canada, fillColor = ~ pal(my_values)) |>
addLegend(pal = pal, values = my_values, opacity = 1.0)
28.2 Tiled map with ggmap
In this section we will use tile maps from Google. To use google maps, you need to have an API key (which may cost money). We will use the ggmap
package to download and draw the map.
There are two steps. First download the tiles needed for your map by specifying
- the bounding box in degrees latitude and longitude, and
- the zoom level of the map.
Always start with a small zoom level – if you make it too big you will download a lot of unnecessary data, which takes time and imposes a burden on the service.
mymap_terrain <- get_googlemap(bbox = c(left = -130, bottom = 41, right = -50, top = 60),
zoom=4, maptype = "terrain")
ggmap(mymap_terrain)
This is a regular ggplot, so you can add lines and points to a map easily, using latitude and longitude as coordinates. Placing text on a map in a readable and attractive way can be quite a challenge.
You can also zoom in on urban areas.
mymap_halifax <- get_googlemap(bbox = c(left = -63.6-0.1, bottom = 44.60, right = -63.6+0.1, top = 44.75),
zoom=12, maptype = "toner-lite")
ggmap(mymap_halifax)
28.3 Packages used
In addition to tidyverse
, I’ve used the following packages
-
leaflet
for making interactive (zoomable, draggable) maps ggmap
-
osmdata
for geolocation functiongetbb
geojsonio
28.4 Further reading
- Healy’s chapter 7 on mapping
- Wilke’s chapter 15 on geospatial data
- An article describing how ggmap works
- A ggmap tutorial, showing how to use Google map services including geocoding (turning an address into a location and the reverse) and routing.
- Another well-developed approach to mapping: mapview