1

我有两个数据集,一个有 488,286 行和经纬度坐标,另一个有 245,077 行和经纬度坐标。第二个还有与坐标相关的附加数据。我想在第二个数据集中找到最接近第一个数据集中的所有点。我不能分享原始数据,所以为了简单起见,我将在这里生成一些随机点:

df1<-cbind(runif(488286,min=-180, max=-120), runif(488286, min=50, max=85))
df2<-cbind(runif(245077,min=-180, max=-120), runif(245077, min=50, max=85))

我尝试只使用 distm 函数,但数据太大,所以我尝试像这样分解它:

library(geosphere)

closest<-apply(df1, 1, function(x){
    mat<-distm(x, df2, fun=distVincentyEllipsoid)
    return(which.min(mat))
})

我认为这行得通,但是运行需要很长时间,以至于我实际上没有看到结果(仅尝试使用数据的子集)。我真的需要一种更快的方法来执行此操作,因为我让它运行了 2 天但没有完成。它不必使用distm,只要更快更准确。

提前致谢!

4

1 回答 1

1

也许这对你有用:

library(sf)
library(RANN)


df1<-data.frame("lon" = runif(2000,min=-180, max=-120), "lat" = runif(2000, min=50, max=85))
df2<-data.frame("lon" = runif(1430,min=-180, max=-120), "lat" = runif(1430, min=50, max=85))



df1_sf <- st_as_sf(df1, coords = c("lon", "lat"), 
         crs = 4326, agr = "constant")

df2_sf <- st_as_sf(df2, coords = c("lon", "lat"), 
                   crs = 4326, agr = "constant")

nearest <- nn2(df2_sf, df1_sf, k = 1, treetype = 'bd', searchtype = 'priority')

df2_sf[nearest$nn.idx,]



RANN是来自 c++ 的 nn 库的包装器,所以它应该很快。尽管如此,我还是减少了这个答案的分数。

首先,我将df1and转换df2sf-objects。然后我将它们提供给nn2-algorithm,这是一个 knn 算法并返回一个列表。列表中的向量包含 中每个点nn.idx的最近点的索引。df2df1

更新:您还可以并行化

library(parallel)

c4 <- parallel::makeCluster(4)

df1_split <- split(df1_sf, cut(1:nrow(df1_sf), 4, labels = FALSE))

clusterExport(c2, "df2_sf")
clusterEvalQ(c2, library(RANN))


system.time(
  idxlist_parallel <- clusterApply(c2, df1_split, 
                                   function(x) nn2(df2_sf, x, k = 1, treetype = 'bd', searchtype = 'priority'))
)
于 2019-04-01T12:39:47.633 回答