简体   繁体   中英

plot ggmap and sf points

I'm struggling to plot a basemap from ggmap with points (sf object). The most promising solution I came across is this SO answer from @andyteucher. I tried to reproduce it below, but I'm not having much luck. I get the basemap to print but not the points.

library(tidyverse)
library(sf)
library(ggmap)

# Define a function to fix the bbox to be in EPSG:3857
# https://stackoverflow.com/a/50844502/841405
  ggmap_bbox <- function(map) {
    if (!inherits(map, "ggmap")) stop("map must be a ggmap object")
    # Extract the bounding box (in lat/lon) from the ggmap to a numeric vector, 
    # and set the names to what sf::st_bbox expects:
    map_bbox <- setNames(unlist(attr(map, "bb")), 
                         c("ymin", "xmin", "ymax", "xmax"))
    
    # Coonvert the bbox to an sf polygon, transform it to 3857, 
    # and convert back to a bbox (convoluted, but it works)
    bbox_3857 <- st_bbox(st_transform(st_as_sfc(st_bbox(map_bbox, crs = 4326)), 3857))
    
    # Overwrite the bbox of the ggmap object with the transformed coordinates 
    attr(map, "bb")$ll.lat <- bbox_3857["ymin"]
    attr(map, "bb")$ll.lon <- bbox_3857["xmin"]
    attr(map, "bb")$ur.lat <- bbox_3857["ymax"]
    attr(map, "bb")$ur.lon <- bbox_3857["xmax"]
    map
  }
# requires API key
  basemap <- get_map(location=c(lon = 75.85199398072335, 
                                lat = 22.7176905515565), 
                     zoom=9, maptype = 'toner-hybrid', 
                     source = 'google')


  basemap_3857 <- ggmap_bbox(basemap)

  points <- tribble(
    ~name, ~lat, ~lon,
    "test1", 22.7176905515565, 75.85199398072335,
    "test2", 22.71802612842761, 75.84848927237663,
  ) %>%
    st_as_sf(coords = c("lat", "lon"),
             crs = 3857)

  ggmap(basemap_3857) + 
    coord_sf(crs = st_crs(3857)) + 
    geom_sf(data = points, 
            inherit.aes = FALSE) 

I believe you had an issue with your coordinate reference systems - you seem to have used degrees in context of CRS 3857, which is defined in meters (and so several degrees of magnitude off...)

If my hunch is correct you need to first declare your sf object to be in 4326 (WGS84 = the CRS of GPS coordinates) and then - and only then - apply transformation to 3857 (from a known start).

Does this code and map fit your expectations? (I also cleaned up the get_map call somewhat, as it had mixed Google and Stamen terms; no big deal there)

# requires API key
basemap <- get_map(location=c(lon = 75.85199398072335, 
                              lat = 22.7176905515565), 
                   zoom=9, 
                   source = 'google')


basemap_3857 <- ggmap_bbox(basemap)

points <- tribble(
  ~name, ~lat, ~lon,
  "test1", 22.7176905515565, 75.85199398072335,
  "test2", 22.71802612842761, 75.84848927237663,
) %>%
  st_as_sf(coords = c("lon", "lat"),
           crs = 4326) %>% # this is important! first declare wgs84
  st_transform(3857) # and then transform to web mercator 

ggmap(basemap_3857) + 
  geom_sf(data = points,
          color = "red",
          inherit.aes = F) 

印多尔红点

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM