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"
inb
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)