Вот игрушечный пример для нахождения массовых расстояний между m
точками и n
городами. Это должно перевести непосредственно к вашей проблеме станции / дома.
Я поднял мировые города, развернул земной шар (так сказать) и остановился на четырех городах. Затем я снова развернулся и остановился на двух точках. Два отсчета здесь несущественны: если у нас есть 4 и 2 или 1100 и 10000, это не должно иметь большого значения.
worldcities <- read.csv(header = TRUE, stringsAsFactors = FALSE, text = "
lat,lon
39.7642548,-104.9951942
48.8588377,2.2770206
26.9840891,49.4080842
13.7245601,100.493026")
coords <- read.csv(header = TRUE, stringsAsFactors = FALSE, text = "
lat,lon
27.9519571,66.8681431
40.5351151,-108.4939948")
(Небольшое примечание ... часто инструменты дают нам координаты в «широте», долгота ", по крайней мере, по моему опыту. geosphere
функции, однако, предполагают" долготу, широту ". Поэтому мои координаты выше были скопированы прямо из случайных видов на картах Google, и я не хотел их редактировать; из-за этого Я переворачиваю столбцы ниже с помощью индексации столбцов [,2:1]
. Если вы забудете и дадите координаты, которые, несомненно, не верны, вы получите ошибку Error in .pointsToMatrix(p1) : latitude < -90
, которая должна быть продуктом, который вы, вероятно, изменили на порядок ваших координат В этот момент вы почесываете голову и удивляетесь, что все ваши другие проекты использовали неправильные координаты, ставя под сомнение ваши выводы. Не я, я никогда там не был. В этом году.)
Давайте найдем расстояние в метрах между каждым из coords
(каждый ряд) и каждым городом (каждый столбец):
dists <- outer(seq_len(nrow(coords)), seq_len(nrow(worldcities)),
function(i, j) geosphere::distHaversine(coords[i,2:1], worldcities[j,2:1]))
dists
# [,1] [,2] [,3] [,4]
# [1,] 12452329.0 5895577 1726433 3822220
# [2,] 309802.8 7994185 12181477 13296825
Оно должно быть прямым чтобы определить, какой город находится ближе всего к каждой координате, с помощью
apply(dists, 1, which.min)
# [1] 3 1
То есть первая точка ближе всего к третьему городу, а вторая точка ближе к первому городу.
Просто чтобы доказать, что это подходящее решение для большого числа пар, вот та же проблема, немного увеличенная.
worldcities_big <- do.call(rbind, replicate(250, worldcities, simplify = FALSE))
nrow(worldcities_big)
# [1] 1000
coords_big <- do.call(rbind, replicate(5000, coords, simplify = FALSE))
nrow(coords_big)
# [1] 10000
system.time(
dists <- outer(seq_len(nrow(coords_big)), seq_len(nrow(worldcities_big)),
function(i, j) geosphere::distHaversine(coords_big[i,2:1], worldcities_big[j,2:1]))
)
# user system elapsed
# 67.62 2.22 70.03
Итак да , это не было мгновенно, но 70 секунд не страшно для 10 000 000 расчётов расстояния. Не могли бы вы сделать это быстрее? Возможно, не уверен точно, как, легко . Я бы подумал, что некоторые эвристики могут уменьшить его до O(m*log(n))
с O(m*n)
времени, но я не знаю, стоит ли это той сложности кодирования, которую он представит.