Sql 通过最近坐标快速(并行)连接大型数据集?

Sql 通过最近坐标快速(并行)连接大型数据集?,sql,r,parallel-processing,data.table,geospatial,Sql,R,Parallel Processing,Data.table,Geospatial,我正在通过最近邻搜索对两个大型固定大小(lat,long)坐标数据集进行SQL风格的连接。目前我正在使用dplyr和data.table来实现这一点。如何为绝对运行时优化和并行我的代码 以前的尝试包括本机python、pandas和多处理,结果非常缓慢。我目前的解决方案是使用data.table构建一个最近邻表,并使用dplyr基于该表进行连接,这是最快的解决方案,但仍然太慢 library(dplyr) library(data.table) library(geosphere) sourc

我正在通过最近邻搜索对两个大型固定大小(lat,long)坐标数据集进行SQL风格的连接。目前我正在使用dplyr和data.table来实现这一点。如何为绝对运行时优化和并行我的代码

以前的尝试包括本机python、pandas和多处理,结果非常缓慢。我目前的解决方案是使用data.table构建一个最近邻表,并使用dplyr基于该表进行连接,这是最快的解决方案,但仍然太慢

library(dplyr)
library(data.table)
library(geosphere)

source <- data.table(lat = runif(1e3), long = runif(1e3)) %>% mutate(nrow = row_number())
dest <- data.table(lat = runif(5e4), long = runif(5e4)) %>% mutate(ind = row_number())
dest_mat <- as.matrix(dest[, c('long', 'lat')])
setDT(source)
# function that returns the index of the closest matching point in dest
mindist_ind <- function(source_lat, source_long) { return(which.min(distHaversine(c(source_long, source_lat), dest_mat))) }


nn_inds <- source[, j = list(ind = mindist_ind(lat, long)), by = 1:nrow(source)] # slowest line, gets index of nearest match in dest
nn_matches <- inner_join(nn_inds, dest, by = 'ind') # join final back to dest in order to get all nearest matches
sourcedest_matches <- inner_join(source, nn_matches, by = 'nrow') # join nearest matches to source by index
库(dplyr)
库(数据表)
图书馆(地球圈)
源%mutate(nrow=row\u number())
目标%mutate(ind=行号()

dest_mat我假设您在问题中提供的代码实际上不是您想要的。您的代码计算
source
dest
的成对行之间的距离,循环
source
以匹配
dest
的长度

您可能想要的,以及这个答案提供的,是在
dest
中为
source
中的每个点找到最近的点。(见我对你问题的评论)

计算距离矩阵需要大量计算。假设R包在计算距离矩阵方面的效率大致相同,那么加快计算速度的唯一方法就是对距离矩阵计算进行并行化。不幸的是,行数较多的矩阵是参考点,因为并行化只能发生在源点的子集上。(即,您需要考虑所有Dist点,以找到最近的<代码> Dist< /代码>指向任何给定的<代码>源<代码> < /P>
库(并行)
图书馆(sp)
#非并行版本

x2
在我的机器上,这需要0秒,可能是因为我有0行数据
也许您可以提供一些可复制的样本数据,我们可以用它们来测试/基准测试东西?当您计时这三个步骤时,哪一个步骤耗时最长?顺便说一句,覆盖
final
会使逻辑难以遵循。如果行集保持不变,您可以就地“更新”表,而不是在每一行上创建一个新表,如data.table简介中所述。@r2Evan这是一个很好的建议-我编辑了生成示例的代码data@Frank到目前为止,成本最高的步骤是构建NNU IND,包含dest中最近匹配项索引的数据表。在我运行的代码中,我对表进行了适当的修改,为了清晰起见,这里对它们进行了分离和命名,这一点很好。我希望优化此部分以更快地运行,或者通过拆分源文件来利用所有可用的内核,因为dest仅在3个处理步骤中读取。可能重复使用
:=as.list
,而不是
:=as.data.table
library(parallel)
library(sp)
#nonparallel version
x2 <- copy(source)
temp <- spDists(x2[, .(long,lat)],dest_mat,longlat=TRUE)
system.time(final2 <- x2[, c("long_dest","lat_dest"):=as.list(dest_mat[apply(temp,1,which.min),]) ])

#parallel version

source_l <- split(source, rep(1:10,each=100))

cl <- makeCluster(getOption("cl.cores", 4))
clusterExport(cl, "dest_mat") #this is slow but I don't think there's a way to get around this

system.time(
  v <- parLapply(cl=cl, X=source_l, fun=function(x){
    library(sp)
    library(data.table)
    temp <- spDists(x[, .(long,lat)],dest_mat,longlat=TRUE)
    x[, c("long_dest","lat_dest"):=as.list(dest_mat[apply(temp,1,which.min),]) ]
    x
  })
)

stopCluster(cl)

final <- rbindlist(v)
identical(final[order(nrow)],final2)