Зачем использовать st_intersection, а не st_intersects? - PullRequest
1 голос
/ 18 июня 2020

st_intersection работает очень медленно по сравнению с st_intersects. Так почему бы не использовать последнее вместо первого? Вот пример с небольшим набором данных игрушек, но разница во времени выполнения огромна для моего фактического набора всего 62 020 точек, пересекающихся с фактической географической границей региона c. У меня 24 ГБ ОЗУ, и код st_intersects занимает несколько секунд, тогда как код st_intersection занимает более 15 минут (возможно, гораздо больше, у меня не хватило терпения ждать ...). Делает ли st_intersection что-нибудь, чего я не получаю с st_intersects?

Приведенный ниже код обрабатывает объекты sfc, но я считаю, что он будет одинаково работать для sf объектов.

library(sf)
library(dplyr)

# create square
s <- rbind(c(1, 1), c(10, 1), c(10, 10), c(1, 10), c(1, 1)) %>% list %>% st_polygon %>% st_sfc
# create random points
p <- runif(50, 0, 11) %>% cbind(runif(50, 0, 11)) %>% st_multipoint %>% st_sfc %>% st_cast("POINT")

# intersect points and square with st_intersection
st_intersection(p, s)

# intersect points and square with st_intersects (courtesy of https://stackoverflow.com/a/49304723/7114709)
p[st_intersects(p, s) %>% lengths > 0,]

1 Ответ

6 голосов
/ 18 июня 2020

Ответ заключается в том, что в целом эти два метода выполняют разные функции, хотя в вашем конкретном случае (поиск пересечения набора точек и многоугольника) st_intersects можно использовать для эффективного выполнения той же работы.

Мы можем показать разницу на простом примере, измененном по сравнению с вашим собственным. Начнем с квадрата:

library(sf)
library(dplyr)

# create square
s <- rbind(c(1, 1), c(10, 1), c(10, 10), c(1, 10), c(1, 1)) %>% 
  list %>% 
  st_polygon %>% 
  st_sfc

plot(s)

enter image description here

Теперь создадим прямоугольник и нарисуем его на том же участке пунктирным контуром:

# create rectangle
r <- rbind(c(-1, 2), c(11, 2), c(11, 4), c(-1, 4), c(-1, 2)) %>% 
  list %>% 
  st_polygon %>% 
  st_sfc

plot(r, add= TRUE, lty = 2)

enter image description here

Теперь мы находим пересечение двух полигонов и наносим его красным цветом:

# intersect points and square with st_intersection
i <- st_intersection(s, r)

plot(i, add = TRUE, lty = 2, col = "red")

enter image description here

Когда мы исследуем объект i, мы увидим, что это новый многоугольник:

i
#> Geometry set for 1 feature 
#> geometry type:  POLYGON
#> dimension:      XY
#> bbox:           xmin: 1 ymin: 2 xmax: 10 ymax: 4
#> epsg (SRID):    NA
#> proj4string:    NA
#> POLYGON ((10 4, 10 2, 1 2, 1 4, 10 4))

Тогда как, если мы используем st_intersects, мы получим только логический результат, говорящий нам, действительно ли существует пересечение между r и s. Если мы попытаемся использовать это для подмножества r, чтобы найти пересечение, мы не получим пересеченную форму, мы просто вернем наш исходный прямоугольник:

r[which(unlist(st_intersects(s, r)) == 1)]
#> Geometry set for 1 feature 
#> geometry type:  POLYGON
#> dimension:      XY
#> bbox:           xmin: -1 ymin: 2 xmax: 11 ymax: 4
#> epsg (SRID):    NA
#> proj4string:    NA
#> POLYGON ((-1 2, 11 2, 11 4, -1 4, -1 2))

Ситуация, которая у вас есть, другая, потому что вы пытаетесь найти подмножество точек, пересекающих многоугольник. В этом случае пересечение группы точек с многоугольником совпадает с подмножеством, отвечающим критерию st_intersects.

Так что здорово, что вы нашли действительный способ более быстрого пересечения . Просто имейте в виду, что это будет работать только с наборами точек, пересекающих многоугольник.

...