Как рассчитать кратчайшее расстояние между точками долготы-широты в одном наборе данных с точками в другом за короткое время - PullRequest
1 голос
/ 01 апреля 2019

У меня есть два набора данных, один с 488 286 строками и координатами долготы и широты, а второй с 245 077 строками и координатами долготы и широты. Второй также имеет дополнительные данные, относящиеся к координатам. Я хочу найти самые близкие точки во втором наборе данных ко всем тем в первом. Я не могу поделиться необработанными данными, поэтому для простоты я сгенерирую здесь несколько случайных точек:

df1<-cbind(runif(488286,min=-180, max=-120), runif(488286, min=50, max=85))
df2<-cbind(runif(245077,min=-180, max=-120), runif(245077, min=50, max=85))

Я пытался использовать только функцию distm, но данные были слишком большими, поэтому я попытался разбить их следующим образом:

library(geosphere)

closest<-apply(df1, 1, function(x){
    mat<-distm(x, df2, fun=distVincentyEllipsoid)
    return(which.min(mat))
})

Я думаю, что это работает, но это занимает так много времени, что я на самом деле не видел результатов (пытался только с подмножеством данных). Мне действительно нужен более быстрый способ сделать это, так как я оставил его включенным на 2 дня, и он не закончился. Не обязательно использовать distm, просто все, что быстрее и точнее.

Заранее спасибо!

1 Ответ

1 голос
/ 01 апреля 2019

Может быть, это работает для вас:

library(sf)
library(RANN)


df1<-data.frame("lon" = runif(2000,min=-180, max=-120), "lat" = runif(2000, min=50, max=85))
df2<-data.frame("lon" = runif(1430,min=-180, max=-120), "lat" = runif(1430, min=50, max=85))



df1_sf <- st_as_sf(df1, coords = c("lon", "lat"), 
         crs = 4326, agr = "constant")

df2_sf <- st_as_sf(df2, coords = c("lon", "lat"), 
                   crs = 4326, agr = "constant")

nearest <- nn2(df2_sf, df1_sf, k = 1, treetype = 'bd', searchtype = 'priority')

df2_sf[nearest$nn.idx,]



RANN - это оболочка для nn-библиотеки из c ++, поэтому она должна быть довольно быстрой. Тем не менее, я уменьшил количество баллов за этот ответ.

Сначала я преобразовал df1 и df2 в sf -объекты. Затем я передал их алгоритму nn2, который является алгоритмом knn и возвращает список. Вектор nn.idx внутри списка содержит индекс для ближайшей точки в df2 для каждой точки в df1.

ОБНОВЛЕНИЕ : Вы также можете распараллелить

library(parallel)

c4 <- parallel::makeCluster(4)

df1_split <- split(df1_sf, cut(1:nrow(df1_sf), 4, labels = FALSE))

clusterExport(c2, "df2_sf")
clusterEvalQ(c2, library(RANN))


system.time(
  idxlist_parallel <- clusterApply(c2, df1_split, 
                                   function(x) nn2(df2_sf, x, k = 1, treetype = 'bd', searchtype = 'priority'))
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...