Базовая карта Google и geom_sf выровнены с пользовательскими символами geom_image и метками комментариев в R - PullRequest
0 голосов
/ 24 августа 2018

Я хотел бы использовать пользовательские символы и аннотации на многоугольном слое geom_sf, который размещен на базовой карте Google. Изначально у меня были проблемы с правильной компоновкой базовой карты и полигона

misaligned polygon image

Так что я использовал это решение для переполнения стека , чтобы исправить это. Теперь базовая карта и слой многоугольника выстраиваются в линию

enter image description here

Но я бы хотел, чтобы пользовательские символы использовали geom_image, а метки - annotate. Немодифицированный слой базовой карты и аннотации с пользовательскими символами работает

misaligned polygon layer with symbols and label

Ниже я расширил код andyteucher и user1453488 и добавил функции geom_image и annotate, которые я хотел бы использовать.

Я попробовал альтернативное решение, построив график с помощью пакета sf, но я не мог понять, как использовать пользовательские символы на графике с широтой и долготой. Мои фактические данные имеют широту и долготу. Я открыт для альтернативных решений, хотя я более знаком с ggmap.

Знаете ли вы, как разместить базовую карту Google, слой многоугольника с точной проекцией, пользовательские символы (сгенерированные из фрейма данных с географическими координатами) и метки на одной карте? Спасибо.

# code modified and expanded from andyteucher's solution
library(ggplot2)
library(ggmap)
library(sf)
library(ggimage)

#load shapefile with sf package
nc <- st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE)

# Transform nc to EPSG 3857 (Pseudo-Mercator, what Google uses)
nc_3857 <- st_transform(nc, 3857)

map <- get_map("north carolina", maptype = "satellite", zoom = 6, source = "google")

# display misaligned polygon with basemap
a <- unlist(attr(map,"bb")[1, ])
bb <- st_bbox(nc)
ggplot() + 
annotation_raster(map, xmin = a[2], xmax = a[4], ymin = a[1], ymax = a[3]) + 
xlim(c(bb[1], bb[3])) + ylim(c(bb[2], bb[4])) + 
geom_sf(data = nc, aes(fill = AREA))

# Define a function to fix the bbox to be in EPSG:3857
 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
}

# Use the function:
mapModified <- ggmap_bbox(map)

 # display aligned polygon with basemap
 ggmap(mapModified) + 
 coord_sf(crs = st_crs(3857)) + # force the ggplot2 map to be in 3857
 geom_sf(data = nc_3857, aes(fill = AREA), inherit.aes = FALSE)

 # create simple data frame for labels and symbols
 name <- c("Point1", "Point2")
 x <- c(-82, -78)
 y <- c(35, 36)
 symbol <- c("https://www.r-project.org/logo/Rlogo.png", 
        "https://jeroenooms.github.io/images/frink.png")
 df <- data.frame(name, x, y, name, symbol)

 # example symbols and label on basemap (but polygon layer misaligned)
 ggplot() + 
  annotation_raster(map, xmin = a[2], xmax = a[4], ymin = a[1], ymax = a[3]) + 
  xlim(c(bb[1], bb[3])) + ylim(c(bb[2], bb[4])) + 
  geom_sf(data = nc, aes(fill = AREA)) +
  annotate("text", -80, 36.5, label = "My text here") +
  geom_image(aes(x, y, image = symbol))

 # after the polygons are aligned the geom_image no longer displays
 ggmap(mapModified) + 
 coord_sf(crs = st_crs(3857)) + # force the ggplot2 map to be in 3857
 geom_sf(data = nc_3857, aes(fill = AREA), inherit.aes = FALSE) + 
 geom_image(aes(x, y, image = symbol))

# after the polygons are aligned the annotate is dropped from display
ggmap(mapModified) + 
coord_sf(crs = st_crs(3857)) + # force the ggplot2 map to be in 3857
geom_sf(data = nc_3857, aes(fill = AREA), inherit.aes = FALSE) + 
annotate("text", -80, 36.5, label = "My text here")
...