R:使用 ggplot、geom_sf 和 openstreetmap 绘制多边形时出现异常错误
R: Unusual error plotting multipolygons with ggplot, geom_sf, and openstreetmap
我正在尝试使用 {ggplot2}、{osmdata} 和 {sf} 绘制 Lake Geneva/Lac Leman。每当我尝试绘制湖泊多面体(其中有 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 package (v0.3.0)
创建于 2019-12-02
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
最后我通过使用 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)
)
由 reprex package (v0.3.0)
于 2019-12-03 创建
这已在 {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 package (v0.3.0)
于 2020-05-26 创建
我正在尝试使用 {ggplot2}、{osmdata} 和 {sf} 绘制 Lake Geneva/Lac Leman。每当我尝试绘制湖泊多面体(其中有 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 package (v0.3.0)
创建于 2019-12-02osmdata 中存在一个问题,如果修复,将来会阻止此问题: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
最后我通过使用 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)
)
由 reprex package (v0.3.0)
于 2019-12-03 创建这已在 {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 package (v0.3.0)
于 2020-05-26 创建