Как поместить карту, созданную geom_sf, поверх растра, созданного ggmap

Я попробовал следующий код:

library(ggplot2)
library(ggmap)
library(sf)
nc <- st_read(system.file("shape/nc.shp", package = "sf"))
str(nc)

 Classes ‘sf’ and 'data.frame':  100 obs. of  15 variables:
 $ AREA     : num  0.114 0.061 0.143 0.07 0.153 0.097 0.062 0.091 0.118 0.124 ...
 $ PERIMETER: num  1.44 1.23 1.63 2.97 2.21 ...
 $ CNTY_    : num  1825 1827 1828 1831 1832 ...
 $ CNTY_ID  : num  1825 1827 1828 1831 1832 ...
 $ NAME     : Factor w/ 100 levels "Alamance","Alexander",..: 5 3 86 27 66 46 15 37 93 85 ...
 $ FIPS     : Factor w/ 100 levels "37001","37003",..: 5 3 86 27 66 46 15 37 93 85 ...
 $ FIPSNO   : num  37009 37005 37171 37053 37131 ...
 $ CRESS_ID : int  5 3 86 27 66 46 15 37 93 85 ...
 $ BIR74    : num  1091 487 3188 508 1421 ...
 $ SID74    : num  1 0 5 1 9 7 0 0 4 1 ...
 $ NWBIR74  : num  10 10 208 123 1066 ...
 $ BIR79    : num  1364 542 3616 830 1606 ...
 $ SID79    : num  0 3 6 2 3 5 2 2 2 5 ...
 $ NWBIR79  : num  19 12 260 145 1197 ...
 $ geometry :sfc_MULTIPOLYGON of length 100; first list element: List of 1
 ..$ :List of 1
 .. ..$ : num [1:27, 1:2] -81.5 -81.5 -81.6 -81.6 -81.7 ...
   ..- attr(*, "class")= chr  "XY" "MULTIPOLYGON" "sfg"
   - attr(*, "sf_column")= chr "geometry"
   - attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA NA NA NA NA NA NA NA ...
   ..- attr(*, "names")= chr  "AREA" "PERIMETER" "CNTY_" "CNTY_ID" ...

map <- get_map("north carolina", maptype = "satellite", zoom = 6, source = "google")
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))

Два слоя не перекрываются должным образом; Я пытался изменить проекцию с coord_sf() но у меня не было успеха.

любое предложение? Спасибо

3 ответа

Я сам боролся с этим, и с помощью этого поста я нашел решение. Ограничительная рамка объекта ggmap находится в WGS84 (EPSG:4326), но фактический растр находится в EPSG:3857. Вы должны взломать ограничивающий прямоугольник объекта ggmap, чтобы он находился в том же CRS, что и базовые данные:

library(ggplot2)
library(ggmap)
library(sf)
#> Linking to GEOS 3.6.2, GDAL 2.3.0, proj.4 5.1.0

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")

# 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:
map <- ggmap_bbox(map)

ggmap(map) + 
  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)

Создано в 2018-06-13 пакетом представлением (v0.2.0).

Вы можете использовать метод построения графика из sf пакет, чтобы сделать это. Вам нужно будет указать систему координат, которую мы должны принять (и это выглядит правильно) 3857.

library(ggplot2)
library(ggmap)
library(sf)

nc_shp <- st_read(system.file("shape/nc.shp", package = "sf"))
nc_map <- get_map("north carolina", maptype = "satellite", zoom = 6, source = "google")

st_crs(nc_map)
# Coordinate Reference System: NA

# assume the coordinate refence system is 3857
plot(st_transform(nc_shp, crs = 3857)[1], bgMap = nc_map)

Все решения хороши, но позвольте мне добавить еще один вариант, который сработал для меня.

Пример использования: наложение дорог Тигра на карту ggmap.

  1. получить дороги и границы (дороги США и штат Огайо):

    US_roads <- primary_roads(); class(US_roads); OH_counties<-counties(state = "OH",year = 2018)

  2. Объединение округов для создания большой геометрии с границами штата Огайо:

    OH_poly <- st_union(OH_counties); plot(OH_poly)

  3. Пересечение дорог в штате Огайо

    OH_roads<-st_intersection(US_roads,OH_poly); plot(OH_roads$geometry)

  4. преобразовать из SF в SP для ggmap, используя вспомогательную функцию для получения интересующей геометрии (например, линии или полигона):

    типы <- vapply(sf::st_geometry(OH_roads), function(x) {class(x)[2]}, "")

    OH_roads2 <- OH_roads[ grepl("*LINE", типы), ]

OH_roads3<-as(OH_roads2, "Пространственный")

      OH_roads3@data$id <- OH_roads3@data$LINEARID
OH_roads4 <- fortify(OH_roads3, region='LINEARID')
  1. Постройте результаты:

    get_stamenmap(bbox, zoom = 10, maptype ="toner") %>% ggmap() + geom_path(data=OH_roads4, aes(long, lat,group = id),alpha=1,size=1,color="#c280e9",lineend = "round")

Другие вопросы по тегам