Reputation: 607
I am trying to find intersecting sfc_LINESTRING
s by group, where both intersecting sfc_LINESTRING
objects are grouped. This question specifically relates to st_intersects
, but I think the workflow will be the same for other operations within sf
. Similar questions have been answered here and here, but in both cases only one of the intersecting objects was grouped and in any case I haven't been smart enough to make it work for my data set.
library(tidyverse)
library(sf)
line1 <- data.frame(lon = c(1, 1.5, 2, 2.5, 2.0, 2.5),
lat = c(1, 1.5, 2, 2.5, 2.1, 2.6),
grp = c("A", "A", "B", "B", "C", "C")
) %>%
st_as_sf(coords = c("lon","lat"), dim = "XY") %>%
group_by(grp) %>%
summarise(do_union = FALSE) %>%
st_cast("LINESTRING") %>%
mutate(grp = c("A","A","B"))
line2 <- data.frame(lon = c(1.2, 1.3, 2.2, 2.3),
lat = c(1, 1.5, 2, 2.5),
grp = c("A", "A", "B", "B")
) %>%
st_as_sf(coords = c("lon","lat"), dim = "XY") %>%
group_by(grp) %>%
summarise(do_union = FALSE) %>%
st_cast("LINESTRING")
plot(line1, lwd = 2, key.pos = 4, reset = FALSE)
plot(line2, lwd = 2, lty = 2, add = TRUE)
I would now like to find the intersecting sfc_LINESTRING
s by the relevant group. Unfortunately, the simple solution I had hoped for using group_by
throws an error:
int <- line1 %>%
group_by(grp) %>%
filter(lengths(st_intersects(line1, line2)) >0)
Using my actual data set, I can get it to run, but the group_by
command seems to be ignored, so that I get all intersecting objects, not just those which match by group. To be specific, in this case the result should only select one sfc_LINESTRING
for each group, i.e. matched continuous and dashed green line and matched continuous and dashed red line. The dashed red line should NOT create an intersection with the green line. Any suggestions will be much appreciated.
Upvotes: 1
Views: 242
Reputation: 4652
Not completely sure if I understood your request correctly, but I am giving it a try! So, please find below one possible solution using the st_join()
function of the sf
library, and then some dplyr
functions to get the final result.
Reprex
library(dplyr)
library(sf)
results <- line1 %>%
st_join(., line2, join = st_intersects) %>%
filter(., grp.x == grp.y) %>%
rename(grp = grp.x) %>%
select(-grp.y)
results
#> Simple feature collection with 2 features and 1 field
#> Geometry type: LINESTRING
#> Dimension: XY
#> Bounding box: xmin: 1 ymin: 1 xmax: 2.5 ymax: 2.6
#> CRS: NA
#> # A tibble: 2 x 2
#> grp geometry
#> <chr> <LINESTRING>
#> 1 A (1 1, 1.5 1.5)
#> 2 B (2 2.1, 2.5 2.6)
plot(results)
PS: In case you want to get the two intersecting lines in each group within the same sf
object, you can extend the code as follows:
results2 <- results %>%
st_union(.,line2, by_feature = TRUE) %>%
filter(., grp == grp.1) %>%
select(-grp.1)
#> Warning: attribute variables are assumed to be spatially constant throughout all
#> geometries
results2
#> Simple feature collection with 2 features and 1 field
#> Geometry type: MULTILINESTRING
#> Dimension: XY
#> Bounding box: xmin: 1 ymin: 1 xmax: 2.5 ymax: 2.6
#> CRS: NA
#> # A tibble: 2 x 2
#> grp geometry
#> <chr> <MULTILINESTRING>
#> 1 A ((1 1, 1.25 1.25), (1.25 1.25, 1.5 1.5), (1.2 1, 1.25 1.25), (1.25 1.25~
#> 2 B ((2 2.1, 2.275 2.375), (2.275 2.375, 2.5 2.6), (2.2 2, 2.275 2.375), (2~
plot(results2)
Created on 2022-01-04 by the reprex package (v2.0.1)
Upvotes: 1