r - 将输出从 sf::st_within 转换为向量
r - Convert output from sf::st_within to vector
我正在尝试使用 R 中的 sf 包来查看 sf 对象是否在另一个具有 st_within
函数的 sf 对象中。我的问题是这个函数的输出是稀疏几何二元谓词 - sgbp
并且我需要一个向量作为输出,以便我可以在之后使用 dplyr
包进行过滤。这是一个简化的例子:
# object 1: I will test if it is inside object 2
df <- data.frame(lon = c(2.5, 3, 3.5), lat = c(2.5, 3, 3.5), var = 1) %>%
st_as_sf(coords = c("lon", "lat"), dim = "XY") %>% st_set_crs(4326) %>%
summarise(var = sum(var), do_union = F) %>% st_cast("LINESTRING")
# object 2: I will test if it contains object 1
box <- data.frame(lon = c(2, 4, 4, 2, 2), lat = c(2, 2, 4, 4,2), var = 1) %>%
st_as_sf(coords = c("lon", "lat"), dim = "XY") %>% st_set_crs(4326) %>%
summarise(var = sum(var), do_union = F) %>% st_cast("POLYGON")
# test 1
df$indicator <- st_within(df$geometry, box$geometry) # gives geometric binary predicate on pairs of sf sets which cannot be used
df <- df %>% filter(indicator == 1)
这给出错误:列 indicator
必须是一维原子向量或列表。
我尝试解决以下问题:
# test 2
df$indicator <- st_within(df$geometry, box$geometry, sparse = F) %>%
diag() # gives matrix that I convert with diag() into vector
df <- df %>% filter(indicator == FALSE)
这行得通,它删除了包含 TRUE 值的行,但是制作矩阵的过程对于我的计算来说非常慢,因为我的真实数据包含很多观察结果。有没有一种方法可以使 st_within
的输出成为字符向量,或者有一种方法可以将 sgbp
转换为与 dplyr
兼容的字符向量而不创建矩阵?
不要直接使用 st_within
函数,而是尝试使用 spatial join
。
查看以下示例 st_joins 如何工作
library(sf)
library(tidyverse)
lines <-
data.frame(id=gl(3,2), x=c(-3,2,6,11,7,10), y=c(-1,6,-5,-9,10,5)) %>%
st_as_sf(coords=c("x","y"), remove=F) %>%
group_by(id) %>%
summarise() %>%
st_cast("LINESTRING")
yta10 <-
st_point(c(0, 0)) %>%
st_buffer(dist = 10) %>%
st_sfc() %>%
st_sf(yta = "10m")
使用左连接保留所有线,但您可以看到其中哪些线位于多边形内
lines %>% st_join(yta10, left=TRUE)
内连接(left = FALSE)只保留里面的那些
lines %>% st_join(yta10, left=FALSE)
后者也可以通过
获得
lines[yta10,]
is_within
的结果实际上是一个列表列,所以你可以使用你的
通过 "unlisting" 解决这个问题吧。像这样的东西会起作用:
library(dplyr)
library(sf)
# object 1: I will test if it is inside object 2 - to make this more interesting
# I added a second not-contained line
df <- data.frame(lon = c(2.5, 3, 3.5), lat = c(2.5, 3, 3.5), var = 1) %>%
st_as_sf(coords = c("lon", "lat"), dim = "XY") %>% st_set_crs(4326) %>%
summarise(var = sum(var), do_union = F) %>% st_cast("LINESTRING")
df2 <- data.frame(lon = c(4.5, 5, 6), lat = c(4.5, 5, 6), var = 2) %>%
st_as_sf(coords = c("lon", "lat"), dim = "XY") %>% st_set_crs(4326) %>%
summarise(var = sum(var), do_union = F) %>% st_cast("LINESTRING")
df3 <- rbind(df, df2)
# object 2: I will test if it contains object 1
box <- data.frame(lon = c(2, 4, 4, 2, 2), lat = c(2, 2, 4, 4,2), var = 1) %>%
st_as_sf(coords = c("lon", "lat"), dim = "XY") %>% st_set_crs(4326) %>%
summarise(var = sum(var), do_union = F) %>% st_cast("POLYGON")
plot(df3)
plot(st_geometry(box), add = TRUE)
# see if the lines are within the box and build a data frame with results
is_within <- st_within(df3$geometry, box$geometry) %>%
lapply(FUN = function(x) data.frame(ind = length(x))) %>%
bind_rows()
# add the "indicator" to df3
df3 <- dplyr::mutate(df3, indicator = is_within$ind)
df3
#> Simple feature collection with 2 features and 2 fields
#> geometry type: LINESTRING
#> dimension: XY
#> bbox: xmin: 2.5 ymin: 2.5 xmax: 6 ymax: 6
#> epsg (SRID): 4326
#> proj4string: +proj=longlat +datum=WGS84 +no_defs
#> var indicator geometry
#> 1 3 1 LINESTRING (2.5 2.5, 3 3, 3...
#> 2 6 0 LINESTRING (4.5 4.5, 5 5, 6 6)
HTH
由 reprex package (v0.2.0) 创建于 2018-03-15。
以下是从稀疏几何二元谓词中获取逻辑向量的方法:
df$indicator <- st_within(df, box) %>% lengths > 0
或在不创建新变量的情况下进行子集化:
df <- df[st_within(df, box) %>% lengths > 0,]
很遗憾,我无法在您的大型数据集上进行测试,但如果它比矩阵方法更快,请告诉我。
我正在尝试使用 R 中的 sf 包来查看 sf 对象是否在另一个具有 st_within
函数的 sf 对象中。我的问题是这个函数的输出是稀疏几何二元谓词 - sgbp
并且我需要一个向量作为输出,以便我可以在之后使用 dplyr
包进行过滤。这是一个简化的例子:
# object 1: I will test if it is inside object 2
df <- data.frame(lon = c(2.5, 3, 3.5), lat = c(2.5, 3, 3.5), var = 1) %>%
st_as_sf(coords = c("lon", "lat"), dim = "XY") %>% st_set_crs(4326) %>%
summarise(var = sum(var), do_union = F) %>% st_cast("LINESTRING")
# object 2: I will test if it contains object 1
box <- data.frame(lon = c(2, 4, 4, 2, 2), lat = c(2, 2, 4, 4,2), var = 1) %>%
st_as_sf(coords = c("lon", "lat"), dim = "XY") %>% st_set_crs(4326) %>%
summarise(var = sum(var), do_union = F) %>% st_cast("POLYGON")
# test 1
df$indicator <- st_within(df$geometry, box$geometry) # gives geometric binary predicate on pairs of sf sets which cannot be used
df <- df %>% filter(indicator == 1)
这给出错误:列 indicator
必须是一维原子向量或列表。
我尝试解决以下问题:
# test 2
df$indicator <- st_within(df$geometry, box$geometry, sparse = F) %>%
diag() # gives matrix that I convert with diag() into vector
df <- df %>% filter(indicator == FALSE)
这行得通,它删除了包含 TRUE 值的行,但是制作矩阵的过程对于我的计算来说非常慢,因为我的真实数据包含很多观察结果。有没有一种方法可以使 st_within
的输出成为字符向量,或者有一种方法可以将 sgbp
转换为与 dplyr
兼容的字符向量而不创建矩阵?
不要直接使用 st_within
函数,而是尝试使用 spatial join
。
查看以下示例 st_joins 如何工作
library(sf)
library(tidyverse)
lines <-
data.frame(id=gl(3,2), x=c(-3,2,6,11,7,10), y=c(-1,6,-5,-9,10,5)) %>%
st_as_sf(coords=c("x","y"), remove=F) %>%
group_by(id) %>%
summarise() %>%
st_cast("LINESTRING")
yta10 <-
st_point(c(0, 0)) %>%
st_buffer(dist = 10) %>%
st_sfc() %>%
st_sf(yta = "10m")
使用左连接保留所有线,但您可以看到其中哪些线位于多边形内
lines %>% st_join(yta10, left=TRUE)
内连接(left = FALSE)只保留里面的那些
lines %>% st_join(yta10, left=FALSE)
后者也可以通过
获得lines[yta10,]
is_within
的结果实际上是一个列表列,所以你可以使用你的
通过 "unlisting" 解决这个问题吧。像这样的东西会起作用:
library(dplyr)
library(sf)
# object 1: I will test if it is inside object 2 - to make this more interesting
# I added a second not-contained line
df <- data.frame(lon = c(2.5, 3, 3.5), lat = c(2.5, 3, 3.5), var = 1) %>%
st_as_sf(coords = c("lon", "lat"), dim = "XY") %>% st_set_crs(4326) %>%
summarise(var = sum(var), do_union = F) %>% st_cast("LINESTRING")
df2 <- data.frame(lon = c(4.5, 5, 6), lat = c(4.5, 5, 6), var = 2) %>%
st_as_sf(coords = c("lon", "lat"), dim = "XY") %>% st_set_crs(4326) %>%
summarise(var = sum(var), do_union = F) %>% st_cast("LINESTRING")
df3 <- rbind(df, df2)
# object 2: I will test if it contains object 1
box <- data.frame(lon = c(2, 4, 4, 2, 2), lat = c(2, 2, 4, 4,2), var = 1) %>%
st_as_sf(coords = c("lon", "lat"), dim = "XY") %>% st_set_crs(4326) %>%
summarise(var = sum(var), do_union = F) %>% st_cast("POLYGON")
plot(df3)
plot(st_geometry(box), add = TRUE)
# see if the lines are within the box and build a data frame with results
is_within <- st_within(df3$geometry, box$geometry) %>%
lapply(FUN = function(x) data.frame(ind = length(x))) %>%
bind_rows()
# add the "indicator" to df3
df3 <- dplyr::mutate(df3, indicator = is_within$ind)
df3
#> Simple feature collection with 2 features and 2 fields
#> geometry type: LINESTRING
#> dimension: XY
#> bbox: xmin: 2.5 ymin: 2.5 xmax: 6 ymax: 6
#> epsg (SRID): 4326
#> proj4string: +proj=longlat +datum=WGS84 +no_defs
#> var indicator geometry
#> 1 3 1 LINESTRING (2.5 2.5, 3 3, 3...
#> 2 6 0 LINESTRING (4.5 4.5, 5 5, 6 6)
HTH
由 reprex package (v0.2.0) 创建于 2018-03-15。
以下是从稀疏几何二元谓词中获取逻辑向量的方法:
df$indicator <- st_within(df, box) %>% lengths > 0
或在不创建新变量的情况下进行子集化:
df <- df[st_within(df, box) %>% lengths > 0,]
很遗憾,我无法在您的大型数据集上进行测试,但如果它比矩阵方法更快,请告诉我。