1

我有两组坐标并试图找到最接近的坐标匹配。鉴于一个数据集包含 100 万条记录,另一个包含近 50 万条记录,正在寻找更好的方法来完成这项任务并需要建议。

第一个数据集的输入是

structure(list(longitude = c(-2.5168477762, -2.5972432832, -2.5936692407, 
-2.5943475677, -2.5923214528, -2.5919014869, -2.5913454553, -2.5835739992, 
-2.5673150195, -2.5683356381), latitude = c(51.4844052488, 51.45278562, 
51.4978889752, 51.4979844501, 51.4983813479, 51.4982126232, 51.4964350456, 
51.4123728037, 51.4266239227, 51.4265740193)), .Names = c("longitude", 
"latitude"), row.names = c(NA, 10L), class = "data.frame")

第二个数据集的输入是

structure(list(longitude = c(-3.4385392589, -3.4690321528, -3.2723981534, 
-3.3684012246, -3.329625956, -3.3093349806, 0.8718409198, 0.8718563602, 
0.8643998472, 0.8644153057), latitude = c(51.1931124311, 51.206897181, 
51.1271423704, 51.1618047221, 51.1805971356, 51.1663567178, 52.896084336, 
52.896092955, 52.9496082626, 52.9496168824)), .Names = c("longitude", 
"latitude"), row.names = 426608:426617, class = "data.frame")

我查看了 R 中的 approx 和 findInterval 函数,但并没有完全理解它们是如何工作的。我想要做的是从 dataset1 获取坐标并将它们与 dataset2 中的所有坐标匹配以找到最接近的匹配。目前我正在使用两个 forloops,但由于数据的大小,它需要很长时间。

我尝试过的代码如下:

cns <- function(x,y)
{
 a = NULL
 b = NULL

for(i=1:nrow(x))  
{
  for(j=1:nrow(y)) 
  { 
      a[j]  = distm(c(x$longitude[i],x$latitude[i]),
                c(y$longitude[j],y$latitude[j]),
                fun = distVincentyEllipsoid)

  } 
  b[i] = which(a == min(a))
}
  return(y[b,])
}

上述函数从 dataset1 中获取一个点并使用 dataset2 中的所有点计算距离,然后找到最小距离并返回该距离的坐标。

寻找可能是并行处理以在合适的时间完成此任务。欢迎任何建议。

问候,

4

1 回答 1

2

1. 尝试向量化你的代码

在 R 中,向量化通常比 for 循环更有效:

  cns2 <- function(x,y){
  b <- numeric(length(nrow(y)))
  for(i in 1:nrow(x)){
    a<- distm(x=x[i,],
                    y=y,
                    fun = distVincentyEllipsoid)

       b[i] = which.min(a)
    }
   return(y[b,])
  }  

让我们评估一下差异:

library(microbenchmark)
microbenchmark(cns(x,y), ###where x is your first dataframe, y the second
               cns2(x,y)
               )

结果:

  Unit: milliseconds
       expr      min       lq     mean   median       uq      max neval
  cns(x, y) 42.46518 45.16829 46.61517 46.45560 47.09023 80.25171   100
 cns2(x, y) 26.09484 27.33122 28.21505 28.07837 29.10225 30.74004   100

在没有并行计算的情况下,您已经将时间减少了一半。我们可以增加更多吗?

cns3 <- function(x,y){
  b <- numeric(length = nrow(y))

  a<- distm(x=x,
              y=y,
              fun = distVincentyEllipsoid)

  b<-apply(X = a,MARGIN =  1, which.min) 
  return(y[b,])
}

基准回报:

    Unit: milliseconds
       expr      min       lq     mean   median       uq       max neval
  cns(x, y) 43.38928 45.69135 48.72223 46.70839 48.56951 135.80555   100
 cns2(x, y) 25.96674 27.15066 28.86999 28.43569 29.99138  35.86383   100
 cns3(x, y) 23.90187 24.84592 26.68738 25.87950 27.99075  34.71469   100

所以cns3似乎快了一点,但是cns2可以通过用foreach替换for轻松实现并行化。

这是对的吗?这三种方法给出相同的输出。

> cns(x,y)
         longitude latitude
426613   -3.309335 51.16636
426613.1 -3.309335 51.16636
426613.2 -3.309335 51.16636
426613.3 -3.309335 51.16636
426613.4 -3.309335 51.16636
426613.5 -3.309335 51.16636
426613.6 -3.309335 51.16636
426613.7 -3.309335 51.16636
426613.8 -3.309335 51.16636
426613.9 -3.309335 51.16636
> cns2(x,y)
         longitude latitude
426613   -3.309335 51.16636
426613.1 -3.309335 51.16636
426613.2 -3.309335 51.16636
426613.3 -3.309335 51.16636
426613.4 -3.309335 51.16636
426613.5 -3.309335 51.16636
426613.6 -3.309335 51.16636
426613.7 -3.309335 51.16636
426613.8 -3.309335 51.16636
426613.9 -3.309335 51.16636
> cns3(x,y)
         longitude latitude
426613   -3.309335 51.16636
426613.1 -3.309335 51.16636
426613.2 -3.309335 51.16636
426613.3 -3.309335 51.16636
426613.4 -3.309335 51.16636
426613.5 -3.309335 51.16636
426613.6 -3.309335 51.16636
426613.7 -3.309335 51.16636
426613.8 -3.309335 51.16636
426613.9 -3.309335 51.16636

2. 通常,当被问及最小值时,当有平局时你想做什么?

使用您编写它的方式,您保持所有联系,这可能会很麻烦,因为 b 可能会在某个点被强制到列表中。

于 2016-03-31T11:28:11.110 回答