Сопоставление адреса с ближайшим мегаполисом

У меня есть набор данных, и я пытаюсь найти местоположение группы в ближайшем мегаполисе. У меня есть набор данных 1 (df1), который содержит адреса с долготой и широтой. Я хочу сопоставить эти адреса со всеми ближайшими мегаполисами (во фрейме данных df2), которые находятся в радиусе 50 миль.

g_lat <- c(45.52306, 40.26719, 34.05223, 37.38605, 37.77493)
g_lon <- c(-122.67648,-86.13490, -118.24368, -122.08385, -122.41942)
address <- c(1,2,3,4,5)
df1 <- data.frame(g_lat, g_lon, address)

g_lat <- c(+37.7737185, +45.5222208,+37.77493)
g_lon <- c(-122.2744317,-098.7041549,-122.41942)
msa <- c(1,2,3)
df2 <- data.frame(g_lat, g_lon, msa)

Я хочу вывести следующее, показывающее все msa, с которыми связан этот адрес:

 address g_lat    g_lon         msa 
  5     37.77493  -122.41942     1
  5     37.77493  -122.41942     3

Пожалуйста, дайте мне знать, как этого можно достичь. Я пробовал следующее:

 library(geosphere)
 # create distance matrix
 mat <- distm(df1[,c('g_lon','g_lat')], df2[,c('g_lon','g_lat')], fun=distVincentyEllipsoid)


  error: 
  Error in .pointsToMatrix(y) : longitude < -360

   # assign the name to the point in list1 based on shortest distance in the matrix
   df1$locality <- df2$locality[max.col(-mat)]

person user3570187    schedule 20.09.2018    source источник
comment
Я проверил ваше решение. Я получаю сообщение об ошибке Ошибка в .pointsToMatrix(y): долгота ‹ -360, я думаю, что точки данных в двух кадрах данных вызывают некоторые трудности, если я использую ваше первое решение. Пожалуйста, порекомендуйте. спасибо   -  person user3570187    schedule 20.09.2018
comment
Не могли бы вы включить код, который вы пробовали, в свой вопрос?   -  person Jaap    schedule 20.09.2018
comment
@Jaap Я обновил код   -  person user3570187    schedule 20.09.2018
comment
Я не получаю это сообщение об ошибке, но эта проблема должна быть решена немного иначе, чем решение, которое я указал выше (если я правильно понимаю вашу проблему). Смотрите мой ответ ниже.   -  person Jaap    schedule 20.09.2018


Ответы (1)


Возможное решение:

library(geosphere)

mat <- distm(df1[,c('g_lon','g_lat')], df2[,c('g_lon','g_lat')], fun=distVincentyEllipsoid)

ri <- row(mat)[mat < 80000]
ci <- col(mat)[mat < 80000]

df3 <- df1[ri,]
df3$msa <- df2[ci, "msa"]

который дает:

> df3
       g_lat     g_lon address msa
4   37.38605 -122.0838       4   1
5   37.77493 -122.4194       5   1
4.1 37.38605 -122.0838       4   3
5.1 37.77493 -122.4194       5   3

С помощью data.table или dplyr:

library(data.table)
setDT(df1)[ri][, msa := df2[ci, "msa"]][]

library(dplyr)
df1 %>% 
  slice(ri) %>% 
  mutate(msa = df2[ci, "msa"])

Вы можете добавить расстояние с помощью:

df3$dist <- mat[cbind(ri, ci)]

который дает:

> df3
       g_lat     g_lon address msa     dist
4   37.38605 -122.0838       4   1 46202.74
5   37.77493 -122.4194       5   1 12774.31
4.1 37.38605 -122.0838       4   3 52359.08
5.1 37.77493 -122.4194       5   3     0.00
person Jaap    schedule 20.09.2018
comment
большое спасибо, можно узнать расстояние до ближайшей МСА? - person user3570187; 20.09.2018
comment
офигенно большое спасибо, что такое ri и ci, это имена строк и столбцов. Если бы мне нужно было получить минимальное значение вместо радиуса 50 миль, я бы использовал df3$near_dist ‹- apply(mat, 1, min), чтобы получить минимальное расстояние msa, большое спасибо, вы сделали мой день! - person user3570187; 21.09.2018
comment
@user3570187 user3570187 ri и ci — это индексы строк и столбцов соответственно; вместо apply(mat, 1, min) вы также можете использовать max.col(-mat), что более эффективно - person Jaap; 21.09.2018