Home > Back-end >  r spatial join-multiple criteria
r spatial join-multiple criteria

Time:02-18

I have two sf datasets and I want to find the 10 closest neighbors, based not only on distance but also on mathcing another column. For example:

a = st_sf(a = 1:3, DD=c("d1","d2","d3"),
 geom = st_sfc(st_point(c(1,1)), st_point(c(2,2)), st_point(c(3,3))))
b = st_sf(a = 11:14,DD=c("d1","d2","d2"),
 geom = st_sfc(st_point(c(10,10)), st_point(c(2,2)), st_point(c(2,2)), st_point(c(3,3))))

I would like to find the neighbors of "a" in "b" having the same value for "DD" col. Currently I am using this approach based on sf and nngeo:

st_join(a, b, join = st_nn, k = 1, progress = FALSE)

But this joins points based on geometry only and I do not know how to get DD into account as well.

Thank you!

I have posted the question also on gis.spatexchange

CodePudding user response:

Not sure to fully understand, but I give it a try! So, please find below one possible solution using only the sf library and some base R functions.

The "strategy" is to transform the dataframes a and b into lists of dataframes according to the DD column (cf. the base R function split()) and then, to perform joins between the dataframe for each DD using the function sf::st_join() and its argument join = st_nearest_feature. Finally, the last operation is to convert the list of results of the different joins into a dataframe using the base R function rbind().

Reprex

  • Code
library(sf)

a <- a[a$DD %in% b$DD,] # added following the OP's comment
b <- b[b$DD %in% a$DD,] # added following the OP's comment

a_list <- split(a, a$DD)
b_list <- split(b, b$DD)

result <- do.call(rbind,Map(st_join, a_list, b_list, MoreArgs = list(join = st_nearest_feature)))
  • Output
result
#> Simple feature collection with 3 features and 4 fields
#> Geometry type: POINT
#> Dimension:     XY
#> Bounding box:  xmin: 1 ymin: 1 xmax: 3 ymax: 3
#> CRS:           NA
#>    a.x DD.x a.y DD.y        geom
#> d1   1   d1  11   d1 POINT (1 1)
#> d2   2   d2  12   d2 POINT (2 2)
#> d3   3   d3  14   d3 POINT (3 3)
  • Data

    NB: I added "d3" in b

a = st_sf(a = 1:3, DD=c("d1","d2","d3"),
          geom = st_sfc(st_point(c(1,1)), st_point(c(2,2)), st_point(c(3,3))))
b = st_sf(a = 11:14,
          DD=c("d1","d2","d2","d3"),geom = st_sfc(st_point(c(10,10)), st_point(c(2,2)), st_point(c(2,2)), st_point(c(3,3))))

Created on 2022-02-17 by the reprex package (v2.0.1)

  • Related