在使用ggplot、geom_sf和openstreetmap绘制多边形时出现了异常错误

6

我正在尝试使用{ggplot2},{osmdata}和{sf}绘制日内瓦湖/莱芒湖。每当我尝试绘制湖泊的多边形(共有5个)时,就会出现错误。我找不到其他地方提到此错误的信息。

library(osmdata)
#> Data (c) OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright
library(tidyverse)

lake_gva <- 
  getbb("Geneva") %>% 
  opq()%>%
  add_osm_feature(key = "natural", value = "water") %>%
  osmdata_sf()

lake_gva
#> Object of class 'osmdata' with:
#>                  $bbox : 46.1777724,6.1102411,46.231885,6.1758527
#>         $overpass_call : The call submitted to the overpass API
#>                  $meta : metadata including timestamp and version numbers
#>            $osm_points : 'sf' Simple Features Collection with 22394 points
#>             $osm_lines : 'sf' Simple Features Collection with 320 linestrings
#>          $osm_polygons : 'sf' Simple Features Collection with 120 polygons
#>        $osm_multilines : NULL
#>     $osm_multipolygons : 'sf' Simple Features Collection with 5 multipolygons

ggplot() +
  geom_sf(
    data = lake_gva$osm_multipolygons
  )
#> Error in do.call(rbind, x): variable names are limited to 10000 bytes

以下是我的会话信息:

sessionInfo()
#> R version 3.6.0 (2019-04-26)
#> Platform: x86_64-apple-darwin15.6.0 (64-bit)
#> Running under: macOS  10.15.1
#> 
#> Matrix products: default
#> BLAS:   /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRblas.0.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib
#> 
#> locale:
#> [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> loaded via a namespace (and not attached):
#>  [1] compiler_3.6.0  magrittr_1.5    tools_3.6.0     htmltools_0.4.0
#>  [5] yaml_2.2.0      Rcpp_1.0.3      stringi_1.4.3   rmarkdown_1.18 
#>  [9] highr_0.8       knitr_1.26      stringr_1.4.0   xfun_0.11      
#> [13] digest_0.6.23   rlang_0.4.2     evaluate_0.14

本代码由reprex包(v0.3.0)于2019年12月02日创建


1
我认为这实际上是osmdata的问题。尝试运行以下代码:q <- lake_gva$osm_multipolygons$geometry[[1]][[1]]; names(q[1]),你应该能看到“长度超过10000字节”的名称。 - agila
3个回答

6
在osmdata中存在一个问题,如果修复了将来会阻止此操作:https://github.com/ropensci/osmdata/issues/188 本质上是因为多边形对象的一部分的名称过长,导致这些名称对于ggplot2来说不可接受。
library(osmdata)
lake_gva <- 
  getbb("Geneva") %>% 
  opq()%>%
  add_osm_feature(key = "natural", value = "water") %>%
  osmdata_sf()

names(lake_gva$osm_multipolygons)

name_polys = lapply(lake_gva$osm_multipolygons$geometry[[1]], names)
sapply(name_polys, nchar)

lake_poly = sf::st_cast(lake_gva$osm_multipolygons$geometry, "POLYGON")
lake_gva$osm_multipolygons$geometry = lake_poly

names(lake_gva$osm_multipolygons$geometry[[2]][[1]]) = NULL]

lake_gva$osm_multipolygons$geometry = unname(lake_gva$osm_multipolygons$geometry)

library(ggplot2)
ggplot() +
  geom_sf(
    data = lake_gva$osm_multipolygons
  )

names(lake_gva$osm_multipolygons$geometry[[1]][[1]][[1]]) = NULL 
names(lake_gva$osm_multipolygons$geometry[[1]][[1]][[2]]) = "lake" 

这有助于展示正在发生的事情,但并不能完全解决您的问题。请参阅此处以了解相关问题的解决方案:https://github.com/rstudio/leaflet/issues/631


只需要使用 lake_gva$osm_multipolygons$geometry <- st_sfc(lapply(lake_gva$osm_multipolygons$geometry, function(i) unname(i)), crs = 4326) 命令删除几何名称。 - mpadge

3

最近更新的{osmdata}软件包已经解决了这个问题。您可以使用以下命令进行安装:

devtools::install_github("ropensci/osmdata")

正如@RobinLovelace提到的那样,问题出在openstreetmap几何图形中包含了命名特征,这是{sf}和{tidyverse}无法处理的。最新版本包括一个辅助函数,将osmdata-sf转换为真正的{sf}对象。这个函数是osmdata::unname_osmdata_sf()。以下是您的代码,添加了该函数以便在ggplot中使用:
library(osmdata)
#> Data (c) OpenStreetMap contributors, ODbL 1.0. https://www.openstreetmap.org/copyright
library(tidyverse)
#> Warning: package 'tibble' was built under R version 3.6.2
#> Warning: package 'purrr' was built under R version 3.6.2

lake_gva <- 
  getbb("Geneva") %>% 
  opq()%>%
  add_osm_feature(key = "natural", value = "water") %>%
  osmdata_sf()

lake_gva_sf <- lake_gva %>% 
  unname_osmdata_sf()
#> Loading required namespace: sf

lake_gva_sf$osm_multipolygons %>% 
  ggplot() + geom_sf()

reprex包 (v0.3.0)于2020年5月26日创建


0
最终,我通过使用sp方法而不是sf方法来进行绘图的变通方法,但希望{osmdata}/{sf}最终能够实现解决方案,以允许使用geom_sf方法。
library(osmdata)
#> Data (c) OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright
library(tidyverse)

lake_gva <-
  getbb("Geneva") %>% 
  opq()%>%
  add_osm_feature(key = "natural", value = "water") %>%
  osmdata_sp()

lake_gva$osm_multipolygons@data$id <- rownames(lake_gva$osm_multipolygons@data)
df_lake_gva <- 
  fortify(lake_gva$osm_multipolygons, region = "id") %>% 
  merge(lake_gva$osm_multipolygons@data, by = "id")
#> Warning in RGEOSUnaryPredFunc(spgeom, byid, "rgeos_isvalid"): Self-intersection
#> at or near point 6.2434241000000004 46.174487800000001
#> SpP is invalid
#> Warning in rgeos::gUnaryUnion(spgeom = SpP, id = IDs): Invalid objects found;
#> consider using set_RGEOS_CheckValidity(2L)

ggplot() +
  geom_polygon(
    data = df_lake_gva,
    aes(x = long, y = lat, group = group)
  )

2019年12月3日由reprex package (v0.3.0)创建


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接