如何在 r 中按最接近的距离合并两个数据集



我有两个数据集 A 和 B,其中包含值和坐标

一个:

╔═══╦════════════╦═════════════╦═════════════╗
║   ║ name       ║ x           ║ y           ║
╠═══╬════════════╬═════════════╬═════════════╣
║ 1 ║ city       ║ 50.3        ║ 4.2         ║
║ 2 ║ farm       ║ 14.8        ║ 8.6         ║
║ 3 ║ lake       ║ 18.7        ║ 9.8         ║
║ 3 ║ Mountain   ║ 44          ║ 9.8         ║
╚═══╩════════════╩═════════════╩═════════════╝

乙:

╔═══╦════════════╦═════════════╦═════════════╗
║   ║ Temp       ║ x           ║ y           ║
╠═══╬════════════╬═════════════╬═════════════╣
║ 1 ║ 18         ║ 50.7        ║ 6.2         ║
║ 2 ║ 17,3       ║ 20          ║ 11          ║
║ 3 ║ 15         ║ 15          ║ 9           ║
╚═══╩════════════╩═════════════╩═════════════╝

我想要这个,C:

╔═══╦════════════╦═════════════╦═════════════╗
║   ║ Name       ║ Temp        ║ Distance    ║
╠═══╬════════════╬═════════════╬═════════════╣
║ 1 ║ city       ║ 18          ║ 2.039608    ║
║ 2 ║ farm       ║ 15          ║ 0.447214    ║
║ 3 ║ lake       ║ 17.3        ║ 1.769181    ║
║ 4 ║ Mountain   ║ 18          ║ 7.605919    ║
╚═══╩════════════╩═════════════╩═════════════╝

我试过这个:

A<- read.table(header = TRUE, text = "
    Name x y 
    city 50.3 4.2
    farm 14.8 8.6
    lake 18.7 9.8
    mountain 44 9.8")
B<- read.table(header = TRUE, text = "
    Temp x y 
    18 50.7 6.2
    17.3 20 11
    15 15 9")
C<- data.frame(Name=character(),
               Temp=numeric(),
               Distance=numeric())
for(i in 1:nrow(A)) {
  x1<- A[i,]$x
  y1<- A[i,]$y
  min = 100
  index = 0
  for(j in 1:nrow(B)) {
    x2<- B[j,]$x
    y2<- B[j,]$y
    tmp = sqrt((((x2-x1)^2)+((y2-y1)^2)))
    if (tmp < min) {
      index = j
      min = tmp
    }
  }
  df <- list(Name=A[i,]$Name, Temp=B[index,]$Temp, Distance=min)
  C <- rbind(C, df)
}
print(C)

但是我的第一个数据集大约有 1,500,000 行,我的第二个数据集大约有 5000 行,这个算法非常非常慢。有没有更好的方法可以做到这一点?

如果你想在 R 中

破解,你可以使用 R 的 outer -函数(以及 R 擅长矢量化的意识(来有效地产生所有 in A[, c(x,y)] 与 all in B[, c(x,y)] 的距离,即获得 A 中位置(行(与B(列(中每个位置的距离矩阵,例如,

A<- read.table(header = TRUE, text = "
               Name x y 
               city 50.3 4.2
               farm 14.8 8.6
               lake 18.7 9.8
               mountain 44 9.8")
B<- read.table(header = TRUE, text = "
               Temp x y 
               18 50.7 6.2
               17.3 20 11
               15 15 9
               18 ")
d <- sqrt(outer(A$x, B$x, "-")^2 + outer(A$y, B$y, "-")^2)
d
##          [,1]      [,2]       [,3]
## [1,]  2.039608 31.053663 35.6248509
## [2,] 35.980133  5.727128  0.4472136
## [3,] 32.201863  1.769181  3.7854986
## [4,]  7.605919 24.029981 29.0110324

接下来,您可以通过 matrixStats 包中的 rowMins -方法有效地获取其值

minD <- matrixStats::rowMins(d)

假设B中有一个唯一的最近位置,则通过(逐行(比较d minD来获取其索引

ind <- (d == minD) %*% 1:ncol(d)

如果B有多个相等距离的位置,您无论如何都需要某种规则来选择哪个。最后,将数据堆叠在一起。

C <- data.frame(Name = A$Name,
                Temp = B$Temp[ind],
                Distance = minD)

最新更新