【问题标题】:How can I use unnest on a list-column of sf objects?如何在 sf 对象的列表列上使用 unnest?
【发布时间】:2019-09-18 13:27:22
【问题描述】:

我有一个由 sf 对象组成的列表列的 tibble。这些 sf 对象中的每一个都有一个或多个多边形行。与取消嵌套 tibbles 列表的方式类似,我希望取消嵌套 sf 对象。

数据看起来像这样

library(sf)
library(tibble)
poly <- st_polygon(list(cbind(c(0,3,3,0,0),c(0,0,3,3,0))))

a = st_sf(st_sfc(poly,poly))
b = st_sf(st_sfc(poly,poly))

df <- tibble(name=c('a','b'),poly=list(a,b))

我希望结果是一个看起来像这样的 sf 对象:

|name | geometry |
|-----|----------|
|a    | POLYGON  |
|a    | POLYGON  |
|b    | POLYGON  |
|b    | POLYGON  |

但是,当我使用 unnest 时,我收到一个错误,并且由于某种原因无法找到 unnest.sf。

编辑:我使用的是 sf 版本 0.7-4

谢谢!

【问题讨论】:

  • 您是否加载了tidyr 以便使用unnest?我正在使用 tidyr 0.8.3,sf 0.7-6 并且可以嵌套到类似于您正在寻找的东西中。这是一个包含polysf 几何的数据框;打电话给st_as_sf 然后给我一个合适的sf 对象
  • @camille 我可以用 tidyr 1.0.0 重现这个。也许是回归?
  • 我正在使用 tidyr 0.8.3 并升级到 sf 0.7-7。我认为它有效,但我收到了一些警告。如果我这样做:st_as_sf(unnest(df))。我得到一个看起来正确的 sf 对象,但我也收到警告消息。也许这很好? “警告消息:1:在 bind_rows_(x, .id) 中:矢量化 'sfc_POLYGON' 元素可能无法保留其属性 2:在 bind_rows_(x, .id) 中:矢量化 'sfc_POLYGON' 元素可能无法保留其属性”

标签: r tidyr sf


【解决方案1】:

按照新术语,unchop() 将比 unnest() 更多。这是一种方法:

library(tidyverse)
library(sf)
#> Linking to GEOS 3.6.1, GDAL 2.2.3, PROJ 4.9.3

poly <- st_polygon(list(cbind(c(0,3,3,0,0),c(0,0,3,3,0))))

a = st_sf(st_sfc(poly,poly))
b = st_sf(st_sfc(poly,poly))

df <- tibble(name=c('a','b'),poly=list(a,b))

unchop_poly <- function(data, col) {
  mutate(data, {{col}} := map({{col}}, ~split(., seq_len(nrow(.))))) %>%
    unchop({{col}})
}
df2 <- df %>% 
  unchop_poly(poly)

df2
#> # A tibble: 4 x 2
#>   name  poly            
#>   <chr> <list>          
#> 1 a     <df[,1] [1 x 1]>
#> 2 a     <df[,1] [1 x 1]>
#> 3 b     <df[,1] [1 x 1]>
#> 4 b     <df[,1] [1 x 1]>

df2$poly
#> [[1]]
#> Simple feature collection with 1 feature and 0 fields
#> geometry type:  POLYGON
#> dimension:      XY
#> bbox:           xmin: 0 ymin: 0 xmax: 3 ymax: 3
#> epsg (SRID):    NA
#> proj4string:    NA
#>               st_sfc.poly..poly.
#> 1 POLYGON ((0 0, 3 0, 3 3, 0 ...
#> 
#> [[2]]
#> Simple feature collection with 1 feature and 0 fields
#> geometry type:  POLYGON
#> dimension:      XY
#> bbox:           xmin: 0 ymin: 0 xmax: 3 ymax: 3
#> epsg (SRID):    NA
#> proj4string:    NA
#>               st_sfc.poly..poly.
#> 1 POLYGON ((0 0, 3 0, 3 3, 0 ...
#> 
#> [[3]]
#> Simple feature collection with 1 feature and 0 fields
#> geometry type:  POLYGON
#> dimension:      XY
#> bbox:           xmin: 0 ymin: 0 xmax: 3 ymax: 3
#> epsg (SRID):    NA
#> proj4string:    NA
#>               st_sfc.poly..poly.
#> 1 POLYGON ((0 0, 3 0, 3 3, 0 ...
#> 
#> [[4]]
#> Simple feature collection with 1 feature and 0 fields
#> geometry type:  POLYGON
#> dimension:      XY
#> bbox:           xmin: 0 ymin: 0 xmax: 3 ymax: 3
#> epsg (SRID):    NA
#> proj4string:    NA
#>               st_sfc.poly..poly.
#> 1 POLYGON ((0 0, 3 0, 3 3, 0 ...

reprex package (v0.3.0) 于 2019 年 9 月 19 日创建

【讨论】:

    【解决方案2】:

    您可以使用data.table 将列表按组绑定在一起,然后转换为sf 对象

    library(sf)
    library(tibble)
    poly <- st_polygon(list(cbind(c(0,3,3,0,0),c(0,0,3,3,0))))
    poly2 <- st_polygon(list(cbind(c(0,1,1,0,0),c(0,0,1,1,0))))
    
    a = st_sf(st_sfc(poly,poly))
    b = st_sf(st_sfc(poly2,poly2))
    
    df <- tibble(name=c('a','b'),poly=list(a,b))
    
    library(data.table)
    
    setDT( df )[, rbindlist( poly ), by = name ] %>% 
      sf::st_as_sf()
    
    
    # Simple feature collection with 4 features and 1 field
    # geometry type:  POLYGON
    # dimension:      XY
    # bbox:           xmin: 0 ymin: 0 xmax: 3 ymax: 3
    # epsg (SRID):    NA
    # proj4string:    NA
    # name             st_sfc.poly..poly.
    # 1    a POLYGON ((0 0, 3 0, 3 3, 0 ...
    # 2    a POLYGON ((0 0, 3 0, 3 3, 0 ...
    # 3    b POLYGON ((0 0, 1 0, 1 1, 0 ...
    # 4    b POLYGON ((0 0, 1 0, 1 1, 0 ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-21
      • 2020-02-04
      • 1970-01-01
      • 1970-01-01
      • 2018-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多