【问题标题】:Calculate distance matrix(non-euclidean) and not using a for loop计算距离矩阵(非欧几里得)而不使用 for 循环
【发布时间】:2018-10-30 10:28:45
【问题描述】:

不使用 for 循环,因为它对于大数据集来说很慢

 A    B
 1    2
-1    4
 9    5
......

我想计算每一行之间的距离并将结果填充到一个矩阵中(就像 dist 所做的但不是正常的距离方法),但是距离是我在不同的场合定义的,所以我不能使用基本的 dist 函数(仅提供固定的指标集)

【问题讨论】:

  • 你好。你真的需要提供更多信息。给出可重现的例子、预期的输出以及你尝试过的和没有成功的。
  • 我在下面添加了我的可重现示例和我的解决方案

标签: r distance


【解决方案1】:

outer 函数提供了一种相当简单的方法来创建自定义距离矩阵,尽管由于您的数据不止一维,您可能需要传入行索引而不是数据。解决方案如下所示:

df <- data.frame(A=c(1,-1,9), B=c(2,4,5)) ##Your data

f <- function(i,j){  ##Some distance function
  (df$A[i]-df$A[j])^4 + (df$B[i]-df$B[j])^4   
}

outer(seq_along(df$A),seq_along(df$A), f)
#     [,1]  [,2]  [,3]
#[1,]    0    32  4177
#[2,]   32     0 10001
#[3,] 4177 10001     0

请注意,函数 f 必须被矢量化,即当 ij 的长度大于 1 时工作

【讨论】:

  • 这需要对f进行向量化,这可能并不容易
  • 在您的帮助下我解决了这个问题,谢谢!我的答案已发布
【解决方案2】:

我解决了这个问题并在这里发布我的答案,以防将来有人需要:

#this create a data set filled with longitude and latitude of some place
temp = structure(list(lon = c(105.948347, 105.956001, 105.9358872, 105.930676, 
105.9300467, 105.933841, 105.958083, 105.947358, 105.9487254, 
105.9471336, 105.948002, 105.9558502, 105.95117, 105.952783, 
105.950688, 105.9441403, 105.944914, 105.9429264, 105.9388434, 
105.938816), lat = c(26.236853, 26.249777, 26.240596, 26.240516, 
26.2438934, 26.245372, 26.242305, 26.244994, 26.2469876, 26.2469411, 
26.2369, 26.2497956, 26.249936, 26.250501, 26.250288, 26.2488675, 
26.250295, 26.2485741, 26.2379629, 26.246864)), .Names = c("lon", 
"lat"), row.names = c(NA, -20L), class = "data.frame")

最终解决方案:

caldistMatrix = function(G,f = distHaversine){
# No need to define G,f since that is in the closure when the func is defined
    calelementdist = function(i,j){
      result = f(p1 = c(G[i,1],G[i,2]),p2 = c(G[j,1],G[j,2]))
      return(result)
    }
  D = outer(seq_along(G[,1]),seq_along(G[,2]),Vectorize(calelementdist))
  return(D)
}

循环解决方案(慢):

caldistMatrix_test = function(G,f = distHaversine){
  D = outer(1:nrow(G),1:nrow(G),Vectorize(function(x,y) return(0)))
  # D = matrix(,nrow = nrow(G),ncol = nrow(G))
  for(i in 1:nrow(G)){
    for(j in 1:nrow(G)){
      D[i,j] = f(p1 = G[i,],p2 =G[j,] )
    }
  }
   return(D)
}

比较:

 system.time(caldistMatrix_test(temp))
 user  system elapsed 
 0.36    0.00    0.40 
 system.time(caldistMatrix(temp))
 user  system elapsed 
 0.14    0.00    0.14 

【讨论】:

    猜你喜欢
    • 2021-03-09
    • 2020-06-16
    • 2015-01-13
    • 2014-05-08
    • 2016-08-02
    • 2012-06-27
    • 2017-01-05
    • 2021-05-24
    相关资源
    最近更新 更多