首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Geosphere的距离矩阵:避免重复计算

Geosphere的距离矩阵:避免重复计算
EN

Stack Overflow用户
提问于 2019-03-04 01:10:42
回答 3查看 123关注 0票数 3

我想使用geosphere中的distm计算一个非常大的矩阵中所有点之间的距离。

请参阅最小示例:

代码语言:javascript
复制
library(geosphere)
library(data.table)

coords <- data.table(coordX=c(1,2,5,9), coordY=c(2,2,0,1))
distances <- distm(coords, coords, fun = distGeo)

问题是,由于我计算的距离的性质,distm给我返回了一个对称矩阵,因此,我可以避免计算超过一半的距离:

代码语言:javascript
复制
structure(c(0, 111252.129800202, 497091.059564718, 897081.91986428, 
111252.129800202, 0, 400487.621661164, 786770.053508848, 497091.059564718, 
400487.621661164, 0, 458780.072878927, 897081.91986428, 786770.053508848, 
458780.072878927, 0), .Dim = c(4L, 4L))

你能帮我找到一种更有效的方法来计算所有这些距离,避免每个距离做两次吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-03-04 01:59:16

如果要计算点x的所有成对距离,最好使用distm(x)而不是distm(x,x)。在这两种情况下,distm函数都返回相同的对称矩阵,但是当您向它传递单个参数时,它知道矩阵是对称的,因此它不会进行不必要的计算。

你可以计时。

代码语言:javascript
复制
library("geosphere")

n <- 500
xy <- matrix(runif(n*2, -90, 90), n, 2)

system.time( replicate(100, distm(xy, xy) ) )
#  user  system elapsed 
# 61.44    0.23   62.79 
system.time( replicate(100, distm(xy) ) )
#  user  system elapsed 
# 36.27    0.39   38.05 

您还可以查看geosphere::distm的R代码,以检查它是否以不同的方式处理这两种情况。

旁白:快速谷歌搜索找到parallelDist:CRAN上的并行距离矩阵计算。测地线距离是一个选项。

票数 2
EN

Stack Overflow用户

发布于 2019-03-04 01:50:21

您可以准备一个没有重复的可能组合的数据帧(使用gtools包)。然后计算这些对的距离。代码如下:

代码语言:javascript
复制
library(gtools)
library(geosphere)
library(data.table)

coords <- data.table(coordX = c(1, 2, 5, 9), coordY = c(2, 2, 0, 1))
pairs <- combinations(n = nrow(coords), r = 2, repeats.allowed = F, v = c(1:nrow(coords)))

distances <- apply(pairs, 1, function(x) {
    distm(coords[x[1], ], coords[x[2], ], fun = distGeo)
})

# Construct distances matrix
dist_mat <- matrix(NA, nrow = nrow(coords), ncol = nrow(coords))
dist_mat[upper.tri(dist_mat)] <- distances
dist_mat[lower.tri(dist_mat)] <- distances
dist_mat[is.na(dist_mat)] <- 0

print(dist_mat)

结果:

代码语言:javascript
复制
         [,1]     [,2]     [,3]     [,4]
[1,]      0.0 111252.1 497091.1 400487.6
[2,] 111252.1      0.0 897081.9 786770.1
[3,] 497091.1 400487.6      0.0 458780.1
[4,] 897081.9 786770.1 458780.1      0.0
票数 2
EN

Stack Overflow用户

发布于 2019-03-04 02:04:23

从基础R使用combn()可能会稍微简单一些,而且可能比加载额外的包更快。然后,distm()使用distGeo()作为源,因此使用后者应该会更快。

代码语言:javascript
复制
coords <- as.data.frame(coords)  # this won't work with data.tables though
cbind(t(combn(1:4, 2)), unique(geosphere::distGeo(coords[combn(1:4, 2), ])))
#      [,1] [,2]     [,3]
# [1,]    1    2 111252.1
# [2,]    1    3 497091.1
# [3,]    1    4 897081.9
# [4,]    2    3 786770.1
# [5,]    2    4 400487.6
# [6,]    3    4 458780.1

我们可以用一个基准测试来检验它。

代码语言:javascript
复制
Unit: microseconds
    expr     min      lq     mean  median       uq     max neval cld
   distm 555.690 575.846 597.7672 582.352 596.1295 904.718   100   b
 distGeo 426.335 434.372 450.0196 441.516 451.8490 609.524   100  a 

看起来不错。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54971461

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档