Возвращает минимальное расстояние между каждой строкой и каждым столбцом двух длинных координат широты в двух кадрах данных - PullRequest
0 голосов
/ 29 апреля 2018

Я хочу рассчитать наименьшее географическое расстояние между каждой строкой и столбцом двух информационных фреймов. DF1 имеет ряд учреждений, а DF2 имеет ряд мероприятий. Мол, так:

#DF1 (institutions)
 DF1 <- data.frame(latitude=c(41.49532, 36.26906, 40.06599), 
 longitude=c(-98.77298, -101.40585, -80.72291))
 DF1$institution <- letters[seq( from = 1, to = nrow(DF1))] 

#DF2 (events)
 DF2 <- data.frame(latitude=c(32.05, 32.62, 30.23), longitude=c(-86.82,   
 -87.67, -88.02))
 DF2$ID <- seq_len(nrow(DF1)

Я хочу вернуть событие с наименьшим расстоянием до каждого учреждения в DF1 и добавить расстояние и ID от DF2 до DF1. Хотя я знаю, как рассчитать попарное расстояние, я не в состоянии рассчитать все расстояния от DF [1,] до DF2 и вернуть наименьшее значение и так далее.

Это то, что я пытался (и не смог).

  library(geosphere)

  #Define a function
   distanceCALC <- function(x, y) { distm(x = x, y = y, 
    fun = distHaversine)}

  #Define vector of events 
   DF2_vec <- DF2[, c('longitude', 'latitude')]

  #Define df to hold distances
   shrtdist <- data.frame()

Теперь, моя попытка состояла в том, чтобы передать distanceCALC строкой DF1 и векторизованными событиями.

  #Loop through every row in DF1 and calculate all the distances to instutions a, b, c. Append to DF1 smallest distance + DF2$ID.

  #This only gives me the pairwise distance
   for (i in nrow(DF1)){
    result  <- distanceCALC(DF1[i,c('longitude', 'latitude')], DF2_vec)
     }
  #Somehow take shortest distance for each row*column distance matrix
   shrtdist <- rbind(shrtdist, min(result[,], na.rm = T))

Я предполагаю, что решение влечет за собой изменение формы данных и их отсутствие. Кроме того, цикл является очень плохой практикой и слишком медленным, учитывая количество наблюдений.

Любая помощь очень ценится.

1 Ответ

0 голосов
/ 29 апреля 2018

Вот простой способ подойти к этому с помощью функции outer

squared_distance <- function(x, y ) (x - y)^2

lat <- outer(DF1$latitude, DF2$latitude, squared_distance)
long <- outer(DF1$longitude, DF2$longitude, squared_distance)

pairwise_dist <- sqrt(lat + long)

rownames(pairwise_dist) <- DF1$institution
colnames(pairwise_dist) <- DF2$ID

pairwise_dist

Это дает вам матрицу расстояний между каждым учреждением (строками) и событием (столбцом). Чтобы получить расстояние и событие в df1, мы можем сделать

df1$min_dist <- apply(pairwise_dist, 1, min)
df1$min_inst <- apply(pairwise_dist, 1, min)

Обратите внимание, что причина, по которой второй работает в этом случае, заключается в том, что события помечены номером. Если ваши реальные данные не имеют такой удобной функции, нам нужно сделать

df1$min_inst <- colnames(pairwise_dist)[apply(pairwise_dist, 1, which.min)]

Обновление с использованием альтернативной функции расстояния

Я не проверял это, но я думаю, что это должно работать. Опять же, на выходе будет матрица.

gcd.hf <- function(DF1, DF2) {
  sin2.long <- sin(outer(DF1$longitude, DF2$longitude, "-") / 2)^2
  sin2.lat  <- outer(DF1$latitude, DF2$latitude, "-")
  cos.lat <- outer(cos(DF1$latitude), cos(DF2$latitude), "*")

  a <- sin2.long + sin2.lat * cos.lat # we do this cell-wise
  cir <- 2 * asin(pmin(1, sqrt(a))) # I never assign anything to "c" since that's concatenate.  Rename this variable as appropriate (I have no idea if it's related to the circumference or not.)
  cir * 6371
}

pairwise_dist <- gcd.hf(DF1, DF2)
...