Как объединить два набора данных по ближайшему расстоянию в r?
У меня есть два набора данных A и B, который содержит значения и координаты
A:
╔═══╦════════════╦═════════════╦═════════════╗
║ ║ 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 ║
╚═══╩════════════╩═════════════╩═════════════╝
B:
╔═══╦════════════╦═════════════╦═════════════╗
║ ║ 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 500000 строк, а мой второй - около 5000, и этот алгоритм очень и очень медленный. Есть ли лучший способ сделать это?
1 ответ
Если вы хотите взломать R, вы можете использовать R outer
-функция (и осознание того, что R хорош в векторизации), чтобы эффективно производить расстояния всех в A[, c(x,y)]
из всех в 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
Затем вы можете эффективно получить его значение с помощью rowMins
-метод в пакете matrixStats
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)