Is this old bug still unresolved, or is there a reasonable workaround yet?
Some cities:
require(ggplot2)
require(ggmap)
require(sf)
cities = sf::read_sf('{
"type": "FeatureCollection",
"name": "cities",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"features": [{
"type": "Feature",
"properties": {
"city": "London"
},
"geometry": {
"type": "Point",
"coordinates": [-0.13, 51.51]
}
},
{
"type": "Feature",
"properties": {
"city": "Rome"
},
"geometry": {
"type": "Point",
"coordinates": [12.48, 41.89]
}
},
{
"type": "Feature",
"properties": {
"city": "Stockholm"
},
"geometry": {
"type": "Point",
"coordinates": [18.07, 59.33]
}
},
{
"type": "Feature",
"properties": {
"city": "Istanbul"
},
"geometry": {
"type": "Point",
"coordinates": [28.96, 41.01]
}
}
]
}
')
And a ggmap basemap:
bb = c(left = -11, bottom = 35, right = 42, top = 65)
europe = ggmap::get_stamenmap(bbox = bb, maptype = 'toner-lite', zoom = 3)
ggmap(europe) +
geom_sf(data = cities, inherit.aes = FALSE, col = 'red', size = 3)
I think the problem is that ggmap
uses the co-ordinate object CoordMap
to decide where to place pixels of a raster. By switching to coord_sf
(which happens when you add a geom_sf
layer), you are knocking the raster out of alignment. If you extract the co-ordinates of your points you can simply overlay them as a geom_point
layer:
ggmap(europe) +
geom_point(data = as.data.frame(st_coordinates(cities)), aes(X, Y),
inherit.aes = FALSE, col = 'red', size = 3)
If you want to be able to draw more complex sf
objects, then I would stay away from ggmap
and use maptiles
:
library(maptiles)
library(tidyterra)
bb <- c(left = -11, bottom = 35, right = 42, top = 65)
europe <- matrix(bb, 2, byrow = TRUE) |>
st_multipoint() |>
st_sfc(crs = 4326) |>
st_transform(3857) |>
get_tiles(provider = "Stadia.Stamen.TonerLite", zoom = 4, crop = TRUE)
ggplot() +
geom_spatraster_rgb(data = europe) +
geom_sf(data = cities, size = 3, color = "red") +
coord_sf(crs = 3857, expand = FALSE, ylim = st_bbox(europe)[c(2, 4)])