Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ggmap in R - keep google copyright information on cropped map

I was wondering if anyone knows how to keep the google copyright information on maps plotted (with a new scale) by ggmap in R?

For example:

library(ggmap)
library(ggplot2)

# download basemap
ggmap::register_google(key="xxx") # insert your hey here xxx
ggmap::ggmap_show_api_key()
base_map <- get_googlemap(center = c(lon= -2.325278, lat=54.6000000), zoom = 5, style = 'element:labels|visibility:off',color= "bw")

When I plot base_map without changing the scale the copyright information is inserted at the bottom of the plot as so:

ggmap(base_map, extent = "panel")

map_with_copyright_info)

However, when I plot base_map with a new x and y axis to zoom into mainland Britain. I also crop off the copyright info. As below:

ggmap(base_map, extent = "panel")+
  scale_x_continuous(limits = c(-7, 3), expand = c(0, 0)) +
  scale_y_continuous(limits = c(49.5, 59), expand = c(0, 0))

map_zoom_noCopyright

Does anyone know how I can get the second plot but with the copyright information that I need for publication?

I have tried to change the zoom= argument in the get_googlemap() function but it always seems to either cut the top or bottom off the UK and I need to be able to see the whole area for when I plot my data.

Thank you so much for your help in advance!

like image 804
QPaps Avatar asked Oct 19 '20 10:10

QPaps


2 Answers

Although seemingly simple, this is actually a quite complex issue. I did some research and found out that you can achieve this by tweaking both size and scale arguments. However, if you are using ggmap v3.0.0 as I do, you will find that specifying non-square dimensions just gives you a "noisy image" as follows:

base_map <- ggmap::get_googlemap(center = c(lon= -2.325278, lat=54.6000000), zoom = 5, size = c(331, 367), style = 'element:labels|visibility:off', color= "bw")
ggmap(base_map, extent = "panel")

noisy map

This involves a known bug in the ggmap package. It has not yet been resolved. Although there exists a solution as mentioned here, that only partially solves the problem because the solution has failed for some cases mentioned in this post. Hence, I'd suggest rewriting that function to make it work in a robust way. Luckily, after investigating the source code, I found the problem not so hard to deal with. The problem results from some image-processing failure in the get_goolemap function. Therefore, outsourcing the image processing in that function to a dedicated package is a simple workaround.

Consider this get_googlemap2 (to make it simple, I have ignored all those argument checkings in the original get_goolemap, so be careful with your inputs)

require(RgoogleMaps)
require(httr)
require(magick)
require(urltools)
require(tibble)

get_googlemap2 <- function(
  api_key = "Your API Key", 
  center = c(lon = -95.3632715, lat = 29.7632836), 
  zoom = 10, size = c(640, 640), scale = 2, 
  maptype = c("terrain", "satellite", "roadmap", "hybrid"), 
  grayscale = FALSE, style
) {
  maptype <- match.arg(maptype)
  
  params <- c(
    center = paste0(center[c(2L, 1L)], collapse = ","), 
    zoom = zoom, 
    size = paste0(size, collapse = "x"), 
    scale = scale, 
    maptype = maptype, 
    style = style, 
    key = api_key
  )
  url <- "https://maps.googleapis.com/maps/api/staticmap"
  urltools::parameters(url) <- paste(names(params), params, sep = "=", collapse = "&")
  url <- URLencode(url)
  
  message("Souce: ", url)
  img <- magick::image_read(httr::content(httr::GET(url)))
  if (grayscale) img <- magick::image_quantize(img, colorspace = "gray")
  ll <- RgoogleMaps::XY2LatLon(
    list(lat = center[2], lon = center[1], zoom = zoom),
    -size[1]/2 + 0.5, -size[2]/2 - 0.5
  )
  ur <- RgoogleMaps::XY2LatLon(
    list(lat = center[2], lon = center[1], zoom = zoom),
    size[1]/2 + 0.5, size[2]/2 - 0.5
  )
  structure(
    as.raster(img), class = c("ggmap", "raster"),
    source = "google", maptype = maptype, zoom = zoom,
    bb = tibble::tibble(ll.lat = ll[1], ll.lon = ll[2], ur.lat = ur[1], ur.lon = ur[2])
  )
}

I tried some specifications of size and scale with this new function and found out that the following specifications render the best map possible.

base_map <- get_googlemap2(
  "Your API Key", 
  center = c(lon = -2.325278, lat = 54.6000000), zoom = 5, size = c(330, 380), scale = 2, style = 'element:labels|visibility:off', grayscale = TRUE
)
ggmap(base_map, extent = "panel")

Output

final_image

I hope this is what you want. I call this the best-possible result because if you attempt to further narrow the width, for example, down to 250, the attribution text will overlap with the logo.

base_map <- get_googlemap2(
  "Your API Key", 
  center = c(lon = -2.325278, lat = 54.6000000), zoom = 5, size = c(250, 380), scale = 2, style = 'element:labels|visibility:off', grayscale = TRUE
)
ggmap(base_map, extent = "panel")

overlap

As far as I can tell, this is Google's problem, not ggmap's. I have no way to solve it. Another workaround would be removing the attribution text from the image but reintroducing it as plain text within the content, as mentioned in Google's attribution guidlines. However, as Google's logo still needs to be there, you then have to figure out how to paste that onto the map. IMO, using plain text gives you greater flexibility in page layouts, and thus might be a better way to go.

like image 127
ekoam Avatar answered Nov 12 '22 01:11

ekoam


I used a lot ggmap, and this type of problem I could not solve then in an elegant way. But there is a way to achieve something like what you want (doing kind of manually). With geom_rect making the lightbox, and with geom_text writing the copyright information.

ggmap(base_map, extent = "panel")+
  scale_x_continuous(limits = c(-7, 3), expand = c(0, 0)) +
  scale_y_continuous(limits = c(49.5, 59), expand = c(0, 0)) +
  geom_rect(ymin = 49.5,ymax = 49.7, fill = 'white', alpha = 0.1, xmin = -3.35, xmax = 3) +
  geom_text(y = 49.6, x = -0.2, size = 2.5,
             label = 'Map data ©2020 GeoBasis-DE/BKG (©2009), Google, Inst. Geogr Nacional') 
ggsave('Map.jpg', width = 7, height = 9, units = 'in')

The size and limits of geom_rect and geom_text must be edited manually according to the size of the save file. In this example, I provide the ggsave I used for it and plot in a nice way.

like image 5
Santiago I. Hurtado Avatar answered Nov 12 '22 00:11

Santiago I. Hurtado