6

Trying to combine dplyr::group_by and sf::st_intersects to see which of the objects within groups in a sf dataframe are intersecting with each other but in the end all objects are compared with all objects in the dataframe irrespective of the groups.

It would be very useful if there is another option package/baseR to do this and limit the comparison of objects within the dataframe and only within a specified group.

Below I have done:
1. create a LINESTRING and a POLYGON
2. used sf::st_intersection to find parts of LINESTRING in the POLYGON
3. convert to LINESTRING
4. check which of the LINESTRINGs are intersecting with each other

library(sf)
library(dplyr)

# sample data
poly <- data.frame(lon = c(-3.5, -1.5, -1.5, -0.5, -0.5, 1, 1, 1.5, 1.5, 7, 7, -3.5, -3.5),
               lat = c(0, 0, 1, 1, 0, 0,1,1,0, 0, 2, 2, 0),
               var = 1) %>%
st_as_sf(coords = c("lon", "lat"), dim = "XY") %>% group_by(var) %>%
summarise(geometry = st_union(geometry), do_union = F) %>% st_cast("POLYGON")

line <- data.frame(lon = c(-4, -3, -2, -2, -3, 2, 2.5, 2, 2), lat = c(0.5, 0.5, 1, 0.5, 1, 0.2, 0.3, 0.4, 0.1), var = 1) %>%
st_as_sf(coords = c("lon", "lat"), dim = "XY") %>% group_by(var) %>%
summarise(geometry = st_union(geometry), do_union = F) %>% 
st_cast("MULTILINESTRING")

# calculating intersection of line with polygon
inters <- st_intersection(line,poly) %>% st_cast("LINESTRING")
inters <- inters %>% mutate(var = c(1,1,2,2,2,2,2,2,2,2,2))

# trying to see which of the linestrings intersect with each other
inters$flag <- inters %>% group_by(var) %>% st_intersects()

This should calculate the intersections between the first two LINESTRINGs separately and between the last 9 LINESTRINGs separately. So intersections of the first LINESTRING with any of the LINESTRINGs from 3 to 11 shouldn`t be calculated.

1
  • 1
    Does tidyr::nest() help any? I tried inters %>% group_by(var) %>% tidyr::nest() %>% mutate(flag = purrr::map(data, st_intersects)) and returned the same result as using sapply() in @sebdalgarno's answer (expect the data are split into two rows of the tibble).
    – Luke1018
    Commented May 18, 2018 at 16:51

1 Answer 1

4

try this, using lapply and split instead of group_by:

inters$flag <- sapply(split(inters, inters$var), function(x) st_intersects(x)) %>% unlist(recursive = FALSE)
2
  • What do you mean by "base R"? Base does not support piping, this is a dpylr syntax appled to a sf function and object. Just because it is wrapped in lapply and split does not make it limited to base operators. Commented Apr 27, 2018 at 17:50
  • I just mean its an alternative to group_by. Sure, there are some pipes in there Commented Apr 27, 2018 at 18:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.