R: более быстрый способ вычисления матрицы больших расстояний

Я вычисляю матрицу расстояний между большим количеством точек (5000) на сфере (используя функцию расстояния Хаверсина).

Вот мой код:

require(geosphere)
x=rnorm(5000)
y=rnorm(5000)
xy1=cbind(x,y)

Время, необходимое для вычисления матрицы расстояний, равно

 system.time( outer(1:nrow(xy1), 1:nrow(xy1), function(i,j) distHaversine(xy1[i,1:2],xy1[j,1:2])))

На выполнение этой программы уходит много времени. Любые предложения, как снизить затраты времени на выполнение этой работы! Спасибо.


person Janak    schedule 24.05.2016    source источник
comment
вы можете попробовать альтернативную реализацию. см. r-bloggers.com/   -  person Leo    schedule 24.05.2016
comment
@Leo с чистой совестью и без намерения оскорбить, я должен указать, что статья по ссылке ужасна! Автор использует цикл for для циклического перехода по вектору для многократного вызова функции (distHaversine()), которая уже векторизована !! Они написали больше кода, одновременно снизив скорость выполнения примерно в 300 раз !!! Не обращайте внимания на эту статью! Вы не вызовете функцию 10 000 раз, хотя подойдет и один раз!   -  person Simon O'Hanlon    schedule 24.05.2016
comment
Привет @ SimonO'Hanlon, спасибо за внимание. :-)   -  person Leo    schedule 24.05.2016


Ответы (2)


Попробовать встроенную функцию в пакете geosphere?

z <- distm( xy1 )

Функция расстояния по умолчанию для distm(), которая вычисляет матрицу расстояний между набором точек, является формулой Хаверсинуса ("distHaversine"), но вы можете указать другую, используя аргумент fun.

На моем Core i7 rMBP с тактовой частотой 2,6 ГГц это занимает около 5 секунд для получения 5000 очков.

person Simon O'Hanlon    schedule 24.05.2016
comment
Спасибо за ваше предложение. Это выполнение занимает меньше половины времени, чем мой код. - person Janak; 24.05.2016

Ниже я добавляю решение с использованием пакета пространственного риска. Ключевые функции в этом пакете написаны на C ++ (Rcpp) и поэтому работают очень быстро.

library(geosphere)
library(spatialrisk)
library(data.table)

x=rnorm(5000)
y=rnorm(5000)
xy1 = data.table(x,y)

# Cross join two data tables
coordinates_dt <- optiRum::CJ.dt(xy1, xy1)

system.time({
  z <- distm( xy1 )
})
# user  system elapsed 
# 14.163   3.700  19.072 

system.time({
  distances_m <- coordinates_dt[, dist_m := spatialrisk::haversine(y, x, i.y, i.x)]
})
# user  system elapsed 
# 2.027   0.848   2.913 
person mharinga    schedule 11.11.2019