Как эффективно рассчитать расстояние между парой координат с помощью data.table: =

Я хочу найти наиболее эффективный (самый быстрый) метод для вычисления расстояний между парами длинных координат лата.

Не столь эффективное решение было представлено (здесь) с использованием sapply и spDistsN1{sp} . Я считаю, что это можно сделать гораздо быстрее, если использовать spDistsN1{sp} внутри data.table с оператором := но я не смог этого сделать. Какие-либо предложения?

Вот воспроизводимый пример :

 # load libraries library(data.table) library(dplyr) library(sp) library(rgeos) library(UScensus2000tract) # load data and create an Origin-Destination matrix data("oregon.tract") # get centroids as a data.frame centroids <- as.data.frame(gCentroid(oregon.tract,byid=TRUE)) # Convert row names into first column setDT(centroids, keep.rownames = TRUE)[] # create Origin-destination matrix orig <- centroids[1:754, ] dest <- centroids[2:755, ] odmatrix <- bind_cols(orig,dest) colnames(odmatrix) <- c("origi_id", "long_orig", "lat_orig", "dest_id", "long_dest", "lat_dest") 

Моя неудачная попытка с использованием data.table

 odmatrix[ , dist_km := spDistsN1(as.matrix(long_orig, lat_orig), as.matrix(long_dest, lat_dest), longlat=T)] 

Вот решение, которое работает (но, вероятно, менее эффективно)

 odmatrix$dist_km  origi_id long_orig lat_orig dest_id long_dest lat_dest dist_km > (chr) (dbl) (dbl) (chr) (dbl) (dbl) (dbl) > 1 oregon_0 -123.51 45.982 oregon_1 -123.67 46.113 19.0909 > 2 oregon_1 -123.67 46.113 oregon_2 -123.95 46.179 22.1689 > 3 oregon_2 -123.95 46.179 oregon_3 -123.79 46.187 11.9014 > 4 oregon_3 -123.79 46.187 oregon_4 -123.83 46.181 3.2123 > 5 oregon_4 -123.83 46.181 oregon_5 -123.85 46.182 1.4054 > 6 oregon_5 -123.85 46.182 oregon_6 -123.18 46.066 53.0709 

2 Solutions collect form web for “Как эффективно рассчитать расстояние между парой координат с помощью data.table: =”

Я написал свою собственную версию geosphere::distHaversine чтобы она более естественно вписывалась в data.table := call, и она может быть data.table здесь

 dt.haversine < - function(lat_from, lon_from, lat_to, lon_to, r = 6378137){ radians <- pi/180 lat_to <- lat_to * radians lat_from <- lat_from * radians lon_to <- lon_to * radians lon_from <- lon_from * radians dLat <- (lat_to - lat_from) dLon <- (lon_to - lon_from) a <- (sin(dLat/2)^2) + (cos(lat_from) * cos(lat_to)) * (sin(dLon/2)^2) return(2 * atan2(sqrt(a), sqrt(1 - a)) * r) } 

Вот некоторые ориентиры в отношении того, как он работает против исходной geosphere::distHaversine и geosphere::distGeo

 dt1 < - copy(odmatrix); dt2 <- copy(odmatrix); dt3 <- copy(odmatrix) library(microbenchmark) microbenchmark( dtHaversine = { dt1[, dist := dt.haversine(lat_orig, long_orig, lat_dest, long_dest)] } , haversine = { dt2[ , dist := distHaversine(matrix(c(long_orig, lat_orig), ncol = 2), matrix(c(long_dest, lat_dest), ncol = 2))] }, geo = { dt3[ , dist := distGeo(matrix(c(long_orig, lat_orig), ncol = 2), matrix(c(long_dest, lat_dest), ncol = 2))] } ) # Unit: microseconds # expr min lq mean median uq max neval # dtHaversine 370.300 396.6210 434.5841 411.4305 463.9965 906.797 100 # haversine 651.974 681.1745 776.6127 706.2760 731.3480 1505.765 100 # geo 647.699 679.8285 743.4914 706.0465 742.1605 1272.310 100 

Естественно, из-за того, как расстояния вычисляются в двух разных методах (geo & haversine), результаты будут немного отличаться.

Благодаря комментарию @ chinsoon12 я нашел довольно быстрое решение, объединяющее distGeo{geosphere} и data.table . В моем ноутбуке быстрые решения были в 120 раз быстрее, чем альтернатива.

Давайте сделаем dataset более крупным, чтобы сравнить скорость работы.

 # Multiplicate data observations by 1000 odmatrix < - odmatrix[rep(seq_len(nrow(odmatrix)), 1000), ] 

медленное решение

 system.time( odmatrix$dist_km < - sapply(1:nrow(odmatrix),function(i) spDistsN1(as.matrix(odmatrix[i,2:3]),as.matrix(odmatrix[i,5:6]),longlat=T)) ) > user system elapsed > 222.17 0.08 222.84 

быстрое решение

 # load library library(geosphere) # convert the data.frame to a data.table setDT(odmatrix) system.time( odmatrix[ , dist_km2 := distGeo(matrix(c(long_orig, lat_orig), ncol = 2), matrix(c(long_dest, lat_dest), ncol = 2))/1000] ) > user system elapsed > 1.76 0.03 1.79 
Interesting Posts

Как восстановить указатель мыши в Gnome

Является ли функция EndInvoke () опциональной, необязательной или необязательной?

Использование JQuery Validate Plugin для проверки нескольких полей формы с одинаковыми именами

Установите службу Windows .NET без InstallUtil.exe

jQuery для сериализации только элементов в div

Как получить размеры представления?

Принудительно просмотреть текстовый файл вместо загрузки в Firefox?

Лучшая практика сохранения настроек приложения в приложении Windows Forms

Как я могу разделить экран с приложениями в полноэкранном режиме?

Как сделать мой случай сравнения строк нечувствительным?

Перетащите файл в приложение под управлением администратора

Как использовать целевой режим в Linux с USB?

Передайте переменную javascript в качестве параметра в @ url.Action ()

Mac, VNC и несколько мониторов

Как работает цветовая палитра tmux?

Давайте будем гением компьютера.