Playing with basemaps

So, before you add any data to your map, you need a baselayer. There are various styles and packages to get these, which I’ve recently learned about - you can just add boundaries of areas but also streets, terrain, or satellite pictures. I particularly like the Stamen map styles. In this post, I will show how I made two basemaps for the UK and Scotland.

When you’re mapping data by colouring in polygons, you don’t really see the baselayer unless you make the top layer transparent, so you might not spend that much time on it. For me, this was more about making something purely for aesthetical appeal!

library(ggmap)
library(sf)

# Let's first try to make a watercolour map of Scotland with get_map by pulling a Google map
# A quick google search for Scotland's coordinates
scotland <- c(lon = -3.188267, lat = 55 )

scotland_map <- get_map(scotland, zoom= 13, maptype = 'watercolor',
                        scale = 1, source = 'stamen') 

This doesn’t work for me, as Google now requires an API key, which you have to pay for after a trial. See ?register_google for details.

Next, I searched for a way to get pretty stamen maps without google API and found a couple of blog posts like this one which were a lot more thorough than this ramble!

I got a shapefile with boundaries of UK countries from ONS.

countries_shp <- st_read("CTRY_DEC_2021_GB_BFC.shp")

colnames(countries_shp)
str(countries_shp)

# Subset the sf object if we want to just look at Scotland
ukmap_sub <- countries_shp[countries_shp$CTRY21NM %in% "Scotland",]

# By using sf's plot, we can create a simple basemap 
plot(st_geometry(ukmap_sub)) # don't just do 'plot', as it will plot every variable and take ages

The basemap with boundaries looks like this:

Scotland basemap

Next, to use “get_stamenmap”, we need to create something called a boundary box, ie. just narrow down the piece of the world you want your map to be framed in. The sf package has the function st_bbox which should create these. In the next piece of code, I feed boundary box the geometry column which contains the coordinates I want to zoom in on. However, get_stamenmap throws an error for me and I haven’t yet figured out why.

borders <- st_bbox(ukmap_sub$geometry)

map <- get_stamenmap(borders, zoom = 5, maptype = "toner-lite")
# this creates an error
# let's check the structure
structure(borders)
 'bbox' Named num [1:4] 5513 530254 470323 1220302
 - attr(*, "names")= chr [1:4] "xmin" "ymin" "xmax" "ymax"
 # it is a bbox object, but the numbers look weird.

However, you can define coordinates yourself like below, and feed get_stamenmap to ggmap.

uk <- c(left = -11, bottom = 49, right = 3, top = 62)

get_stamenmap(uk, zoom = 5, "toner-lite") %>% ggmap()

# this gives us a stamen basemap 

# let's try another nicer style
get_stamenmap(uk, zoom = 5, "watercolor") %>% ggmap()

There we go! That’s so nice you don’t want to overlay any data on it.

UK watercolour basemap