在sf中测试/过滤器几何的相等性?

时间:2017-11-07 03:15:02

标签: r dplyr geospatial purrr sf

可能会遗漏一些东西,但是经过一堆挖掘后却找不到任何东西。我试图找到几何占一定值的sf个对象行。这是为了整理目的,其中相同的几何图形可能与不同的数据集中的不同关联元数据(例如id和其他值)一起存储,我需要解决差异。

通常情况下,使用dplyr过滤特定值很容易,如下所示:

加载所需的包

library(tidyverse)
#> Loading tidyverse: ggplot2
#> Loading tidyverse: tibble
#> Loading tidyverse: tidyr
#> Loading tidyverse: readr
#> Loading tidyverse: purrr
#> Loading tidyverse: dplyr
#> Conflicts with tidy packages ----------------------------------------------
#> filter(): dplyr, stats
#> lag():    dplyr, stats
library(sf)
#> Linking to GEOS 3.6.1, GDAL 2.2.0, proj.4 4.9.3

加载示例数据集

nc <- st_read(system.file("shape/nc.shp", package="sf"))
#> Reading layer `nc' from data source `C:\Users\Calum You\Documents\R\win-library\3.4\sf\shape\nc.shp' using driver `ESRI Shapefile'
#> Simple feature collection with 100 features and 14 fields
#> geometry type:  MULTIPOLYGON
#> dimension:      XY
#> bbox:           xmin: -84.32385 ymin: 33.88199 xmax: -75.45698 ymax: 36.58965
#> epsg (SRID):    4267
#> proj4string:    +proj=longlat +datum=NAD27 +no_defs

正如预期的那样,dplyr::filter适用于不同的列。我们可以轻松选择NAME Ashe和CNTY_ID 1825这一行,这是第一行:

nc %>% filter(NAME == "Ashe")
#> Simple feature collection with 1 feature and 14 fields
#> geometry type:  MULTIPOLYGON
#> dimension:      XY
#> bbox:           xmin: -81.74107 ymin: 36.23436 xmax: -81.23989 ymax: 36.58965
#> epsg (SRID):    4267
#> proj4string:    +proj=longlat +datum=NAD27 +no_defs
#>    AREA PERIMETER CNTY_ CNTY_ID NAME  FIPS FIPSNO CRESS_ID BIR74 SID74
#> 1 0.114     1.442  1825    1825 Ashe 37009  37009        5  1091     1
#>   NWBIR74 BIR79 SID79 NWBIR79                       geometry
#> 1      10  1364     0      19 MULTIPOLYGON (((-81.4727554...
nc %>% filter(CNTY_ID == 1825)
#> Simple feature collection with 1 feature and 14 fields
#> geometry type:  MULTIPOLYGON
#> dimension:      XY
#> bbox:           xmin: -81.74107 ymin: 36.23436 xmax: -81.23989 ymax: 36.58965
#> epsg (SRID):    4267
#> proj4string:    +proj=longlat +datum=NAD27 +no_defs
#>    AREA PERIMETER CNTY_ CNTY_ID NAME  FIPS FIPSNO CRESS_ID BIR74 SID74
#> 1 0.114     1.442  1825    1825 Ashe 37009  37009        5  1091     1
#>   NWBIR74 BIR79 SID79 NWBIR79                       geometry
#> 1      10  1364     0      19 MULTIPOLYGON (((-81.4727554...

尝试在几何列上进行过滤时效果不佳。我希望这只返回nc的第一行,因为那是nc的行,其中geometry等于(根据定义)第一个几何`nc $ geometry [1 ]”。

nc %>% filter(geometry == nc$geometry[1])
#> Error in filter_impl(.data, quo): Evaluation error: operation == not supported.
nc %>% filter(geometry == st_geometry(nc)[1])
#> Error in filter_impl(.data, quo): Evaluation error: operation == not supported.

错误消息表明即使==运算符也不起作用:

nc$geometry[1] == nc$geometry[1]
#> Error in Ops.sfc(nc$geometry[1], nc$geometry[1]): operation == not supported

identical()有效,但不是为了构建我自己的过滤器。希望看到TRUE作为输出的第一个元素,但我不认为identical()在地图函数中的作用与此类似。

identical(nc$geom[1], nc$geom[1])
#> [1] TRUE
map_lgl(nc$geometry, function(x) identical(x, nc$geometry[1]))
#>   [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#>  [12] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#>  [23] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#>  [34] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#>  [45] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#>  [56] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#>  [67] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#>  [78] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#>  [89] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [100] FALSE

==中的几何图形是否sf根本没有定义?如果是这样,是否有替代方法可以测试相等性或以其他方式查找不同数据集中相同的几何?我即将使用rbind个不同的数据集并使用duplicated()来执行此操作,但这需要确保两者中的所有列都相同并且看起来像是意外/不必要的麻烦。

感谢您提出问题的结尾 - 非常感谢任何建议!

1 个答案:

答案 0 :(得分:1)

似乎确实没有为sf对象定义==。但是,identical()可用于此目的,如果您记得在子集中向下钻取,如cuttlefish44所述。例如,这可以正常工作:

identical(nc$geom[[1]], nc$geom[[1]])
map_lgl(nc$geometry, function(x) identical(x, nc$geometry[[1]]))
  [1]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [22] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [43] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [64] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [85] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

我认为这与我对sf如何存储几何的混淆有关:sfg实际上不是一个列表,而是包含几何的点列表。无论如何,很高兴能找到解决方法。

编辑:我没有意识到st_equals中已实现sf。它具有不同的语法,但可能是用于此目的的最佳工具,因为它描述了区域相等而不是数据结构相等。