【问题标题】:Creating a distance matrix between companies based on their geographical locations根据地理位置创建公司之间的距离矩阵
【发布时间】:2015-10-29 10:25:35
【问题描述】:

我想使用地理位置创建公司之间的距离矩阵。

我有一个平方距离矩阵,其中包含 98 个意大利省份之间的距离。我还有一个包含两列的数据框。一栏有 8376 家公司的 ID 号。另一列表示这些公司各自位于 98 个省中的哪个省。

我想创建一个 8376 x 8376 距离矩阵,其中包含所有公司之间的距离。我编写的代码(如下)效率极低。有没有办法更快地做到这一点?我问是因为我需要对多个数据集进行此操作。

这就是数据框的样子

   cid province
1  61       TO
2 102       TO
3 123       AT
4 127       TO
5 158       TO
6 225       NO
7 232       TO
8 388       TO

这就是平方距离矩阵的样子

     CH     AQ      PE       TE
1     0  64.39   41.74    81.18
2 64.39   0      40.38    61.05
3 41.74  40.38    0       40.79
4 81.18  61.05   40.79     0              


outcome = matrix(NA,8376,8376)  # empty matrix

for(i in 1:8376){
  for(j in (i+1):8376){
    x=which(dist.codes[,1]==companyID_Province[i,2]) # Find the row index in the distance matrix 
    y=which(dist.codes[1,]==companyID_Province[j,2]) # Find the column index in the distance matrix
    outcome[i,j] = dist.codes[x,y] # Specify the distance to the corresponding element in outcome matrix
  }
}

【问题讨论】:

  • 请提供一个可重现的例子。显示dist.codescompany_Province 的一小部分。
  • 在您的代码中,outcome[i,j] = dist.codes[x,y] 表明dist.codes 是各省的距离矩阵。但随后y=which(dist.codes[1,]==companyID_Province[j,2]) 将距离与公司 ID 进行比较。
  • dist.codes 是各省的距离矩阵。 x 是行索引,y 是列索引。两者都使用 companyID_Province 数据框。我现在已经更正了,和以前一样有一个错误。在我运行的代码中它是正确的,但仍然需要 24 小时以上,因为有数百万个单元格要填充
  • 嗨 Nicola,我目前正在运行代码,所以我现在不能发布子集。我今天晚些时候会做(如果运行终止)。数据框“companyID_Province”为 8376*2。平方距离矩阵“dist.codes”为 98*98
  • 您的代码只使用了一列companyID_Province,即第二列。第一列有什么用?第二列是否包含 ID 或省份?

标签: r matrix distance spatial


【解决方案1】:

如果dist.codes是省份的距离矩阵,province[i]是ID为i的公司所在的省份,那么dist.codes[province,province]是公司的距离矩阵。 如果companycompany$ID中的公司ID和company$province中的省号的数据框,那么company$province[order(company$ID)]是上面的向量province,按公司ID排序。

我已将您的代码与我的提案进行了比较:

SpeedComparison <- function(N,M)
{
  set.seed(1)

  dist.codes <- matrix(sample(1:1000,N*N,rep=TRUE),N,N) / 100
  dist.codes <- dist.codes * t(dist.codes)
  diag(dist.codes) <- 0
  dist.codes <- cbind(0:N,rbind(1:N,dist.codes)) # Add an additional row and an additional column with province numbers.

  companyID_Province <- data.frame( ID = 1:M, province = sample(1:N,M,replace=TRUE) )

  #---------------------------------------------------------------------

  tm.1 <- 0.01 * system.time(
    for ( i in 1:100)
    {
      outcome.1 = matrix(0,M,M)  # empty matrix

      for(i in 1:(M-1)){
        x=which(dist.codes[,1]==companyID_Province[i,2]) # Find the row index in the distance matrix 
        for(j in (i+1):M){
          y=which(dist.codes[1,]==companyID_Province[j,2]) # Find the column index in the distance matrix
          outcome.1[i,j] = dist.codes[x,y] # Specify the distance to the corresponding element in outcome matrix
        }
      }
    }
  )

  tm.2 <- 0.01 * system.time(
    for ( i in 1:100)
    {
      D <- dist.codes[-1,][,-1] # The additional row/column is not used here.
      outcome.2 <- D[companyID_Province[,2],companyID_Province[,2]]
    }
  )

  list( outcome = list( outcome.1+t(outcome.1), outcome.2 ),
        time    = list( tm.1, tm.2 ) )
}

#======================================================================

N <- 50

Comparison <- as.data.frame(matrix(NA,0,4))

for ( M in c(100,150,200,250,300) )
{
  Test <- SpeedComparison(N,M)

  Comparison <- rbind( Comparison,
                       c( M,
                          Test$time[[1]][3],
                          Test$time[[2]][3],
                          identical(Test$outcome[[1]],Test$outcome[[2]])))
}  

names(Comparison) <- c("M","time.1","time.2","outcomes.identical")

outcomes 相等(“1”表示 TRUE),时间不相等:

> Comparison
    M time.1 time.2 outcomes.identical
1 100 0.2568  2e-04                  1
2 150 0.5661  5e-04                  1
3 200 1.1845  7e-04                  1
4 250 1.9568  1e-03                  1
5 300 2.8602  4e-03                  1
> 

【讨论】:

  • 嗨,对不起,我对你的回答感到困惑。该代码有效,但效率极低。我正在寻找一种替代方法来实现相同的目标。任何建议将不胜感激
  • @PaulWagner 您需要矢量化您的代码。但是你没有给reproducible example,这让任何人都很难帮助你。 mra68 在这里做得很好......如果你想要一个“更好”的答案,你需要提供一个更好的问题 - IE 一个具有可重现数据的问题。
  • @PaulWagner:通过与您的代码(包括速度测试)的比较,我增强了我的答案。如果你还是一头雾水,我建议你不要简单套用我的解决方案,而是先试着去理解它。这样你就可以了解 R。
  • "mra68 谢谢。我会在今天早上完成。感谢您的时间
猜你喜欢
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 2015-06-11
  • 2021-03-27
  • 1970-01-01
  • 2011-09-21
  • 2021-09-23
  • 2020-09-11
相关资源
最近更新 更多