r - 使用 map2 将 st_intersection 应用于嵌套数据框
问题描述
尝试将函数应用于嵌套数据框。数据样本:
# 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
解决方案
问题是在输入中并行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)
对于这个特定的示例,首先取消嵌套会更有意义,但大概您有一种情况,这种方法不太理想。
推荐阅读
- angular - 如何规范化ngrx/store中的深层嵌套数据?
- vue.js - 如何按字母顺序对 Vue.js / Buefy 形式的选项列表进行排序?
- powershell - Set-WebBinding 可以将协议从 HTTP 更改为 HTTPS 吗?
- rest - 发送 REST 请求获取 Postman 获取的数据
- python - 从网站上的表单中交互式抓取数据
- c# - 默认空泛型类型
- java - weblogic服务器中的jsf安全领域
- arrays - 如何合并与其他数组中的属性匹配的对象数组
- javascript - React.js Redux reducer 不插入项目
- api - [团队]如何通过 API 或 SDK 更新消息传递端点?