hugh-allan
hugh-allan

Reputation: 1370

How to use API key in annotation_map_tile() in ggplot

Is there a way an API key can be used to get a basemap for a map on ggplot? I've got a Thunderforest API key and want to use the "landscape" layer with a zoom level of 15. Looks like zoom 14 and beyond has the "API required" watermark*.

I've followed through the code and answer here: How to pass Thunderforest API key to the R ggspatial package to create a map but I get an error when I run:

thunderforest = source_from_url_format(
  url_format = c('http://a.tile.thunderforest.com/landscape/${z}/${x}/${y}.png?apikey=<my_api>',
                 'http://b.tile.thunderforest.com/landscape/${z}/${x}/${y}.png?apikey=<my_api>',
                 'http://c.tile.thunderforest.com/landscape/${z}/${x}/${y}.png?apikey=<my_api>'),
)

I get the following error:

Error in match.arg(extension, c("png", "jpeg", "jpg")) : 
  'arg' should be one of “png”, “jpeg”, “jpg”

And yes I replaced <my_api> with my actual API

For reference, this is an example of the map I am trying to make

library(tidyverse)
library(sf)
library(ggspatial)


tibble(
  lat = 148.652, 
  lon = -35.600
) %>% 
  st_as_sf(
    x = ., 
    crs = 4326, 
    coords = c('lat', 'lon')
  ) %>% 
  {. ->> my_point}


ggplot()+
  geom_sf(data = my_point)+
  annotation_map_tile(alpha = 0.7, type = 'thunderforestlandscape', zoom = 16)+
  coord_sf(
    xlim = c(148.64, 148.66), 
    ylim = c(-35.61, -35.59)
  )

And the current output has the "API required" watermark.

enter image description here

EDIT 2024-05-30

Thanks Felix for the suggestion, but even when I include extension = 'png' in url_format(), it still doesn't work. The url_format() call doesn't return an error, but when included as the type in annotation_map_tile() we get an error:

my_api <- '123myapi456'

my_thunderforest = source_from_url_format(
  url_format = c('http://a.tile.thunderforest.com/landscape/${z}/${x}/${y}.png?apikey=my_api',
                 'http://b.tile.thunderforest.com/landscape/${z}/${x}/${y}.png?apikey=my_api',
                 'http://c.tile.thunderforest.com/landscape/${z}/${x}/${y}.png?apikey=my_api')
  )

# Error in match.arg(extension, c("png", "jpeg", "jpg")) :
#   'arg' should be one of “png”, “jpeg”, “jpg”


# let's try 'extension = png'

my_thunderforest = source_from_url_format(
  url_format = c('http://a.tile.thunderforest.com/landscape/${z}/${x}/${y}.png?apikey=my_api',
                 'http://b.tile.thunderforest.com/landscape/${z}/${x}/${y}.png?apikey=my_api',
                 'http://c.tile.thunderforest.com/landscape/${z}/${x}/${y}.png?apikey=my_api'),
  extension = 'png'
)

ggplot()+
  geom_sf(data = my_point)+
  annotation_map_tile(alpha = 0.7, type = my_thunderforest, zoom = 16)+
  coord_sf(
    xlim = c(148.64, 148.66),
    ylim = c(-35.61, -35.59)
  )

# Error in as.data.frame.default(x[[i]], optional = TRUE, stringsAsFactors = stringsAsFactors) :
#   cannot coerce class ‘"tile_source"’ to a data.frame

*After trying to make some maps with larger bounding boxes and smaller values of zoom it looks like maybe the API requirement isn't zoom related, but instead the number of tiles required for the map. Even so, I assume it requires the same solution as the main example here.

Upvotes: 0

Views: 114

Answers (0)

Related Questions