【问题标题】:Apply st_intersection to a nested dataframe with map2使用 map2 将 st_intersection 应用于嵌套数据框
【发布时间】:2018-09-12 18:58:05
【问题描述】:

尝试将函数应用于嵌套数据框。数据样本:

# required packages
library(dplyr)
library(sf)
library(tidyr)
library(purrr)

# sample data
ln1 <- data.frame(
  id = c(1,1,2,2),
  lon = c(1,4,4,9),
  lat = c(2,9,9,5)
)

ln2 <- data.frame(
  id = c(1,1,2,2),
  lon = c(3,3,6,6),
  lat = c(15,0,15,0)
)

# function for creating an "sf" object
make_sf_lns <- function(x) {
  x %>% st_as_sf(coords = c("lon", "lat"), dim = "XY") %>% 
    st_set_crs(4326) %>% 
    group_by(id) %>% summarise(geometry = st_union(geometry)) %>% 
    st_cast("LINESTRING")
}

# converting data to "sf" objects - "LINESTRING"s
ln1 <- make_sf_lns(ln1)
ln2 <- make_sf_lns(ln2)

以下代码行代表我打算做的事情:

st_intersection(ln1, ln2)

但出于特定原因,我需要将st_intersection 应用于嵌套数据框,如下所示:

# implementation with `tidyr::nest` and `purrr::map2`
ln1 <- ln1 %>% group_by(id) %>% nest()

map2(ln1$data, ln2, ~ st_intersection(.x, .y))

当我这样做时,预期的结果是一个带有交叉点的嵌套数据框,但会出现以下错误:

Error in st_crs(x) == st_crs(y) : Expecting a single value: [extent=2].
In addition: Warning message:
In if (is.na(x)) NA_crs_ else if (inherits(x, "crs")) x else if 
(is.numeric(x)) CPL_crs_from_epsg(as.integer(x)) else if (is.character(x)) { :
  the condition has length > 1 and only the first element will be used

【问题讨论】:

    标签: r nested tidyr purrr sf


    【解决方案1】:

    问题在于map2 迭代并行 跨输入,因此除了迭代列表列之外,它还尝试迭代ln2 的变量。相反,使用map,并在函数内部或之后指定第二个参数:

    # iterate across the data column of this
    ln1
    #> # A tibble: 2 x 2
    #>      id data        
    #>   <dbl> <list>      
    #> 1     1 <sf [1 × 1]>
    #> 2     2 <sf [1 × 1]>
    
    # don't iterate across the columns of this
    ln2
    #> Simple feature collection with 2 features and 1 field
    #> geometry type:  LINESTRING
    #> dimension:      XY
    #> bbox:           xmin: 3 ymin: 0 xmax: 3 ymax: 15
    #> epsg (SRID):    4326
    #> proj4string:    +proj=longlat +datum=WGS84 +no_defs
    #>   id               geometry
    #> 1  1 LINESTRING (3 0, 3 15)
    #> 2  2 LINESTRING (6 0, 6 15)
    
    # equivalent: map(ln1$data, ~st_intersection(.x, ln2))
    map(ln1$data, st_intersection, ln2)
    #> although coordinates are longitude/latitude, st_intersection assumes that they are planar
    #> Warning: attribute variables are assumed to be spatially constant
    #> throughout all geometries
    #> although coordinates are longitude/latitude, st_intersection assumes that they are planar
    #> Warning: attribute variables are assumed to be spatially constant
    #> throughout all geometries
    #> [[1]]
    #> Simple feature collection with 1 feature and 1 field
    #> geometry type:  POINT
    #> dimension:      XY
    #> bbox:           xmin: 3 ymin: 6.666667 xmax: 3 ymax: 6.666667
    #> epsg (SRID):    4326
    #> proj4string:    +proj=longlat +datum=WGS84 +no_defs
    #>   id           geometry
    #> 1  1 POINT (3 6.666667)
    #> 
    #> [[2]]
    #> Simple feature collection with 1 feature and 1 field
    #> geometry type:  POINT
    #> dimension:      XY
    #> bbox:           xmin: 6 ymin: 7.4 xmax: 6 ymax: 7.4
    #> epsg (SRID):    4326
    #> proj4string:    +proj=longlat +datum=WGS84 +no_defs
    #>   id      geometry
    #> 1  2 POINT (6 7.4)
    

    对于这个特定的示例,首先取消嵌套会更有意义,但可能您遇到的情况不太理想。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-15
      • 2021-11-03
      相关资源
      最近更新 更多