two geographic disthaversine r distance latitude-longitude

geographic - Distancia geográfica/geoespacial entre 2 listas de puntos lat/lon(coordenadas)



geographic distance in r (2)

Tengo 2 listas ( list1 , list2 ) con latitud / longitud de varias ubicaciones. Una lista ( list2 ) tiene nombres de localidad que list1 no tiene.

También quiero una localidad aproximada para cada punto de la lista1. Entonces quiero tomar un punto en la list1 , tratar de buscar el punto más cercano en la list2 y tomar esa localidad. Repito para cada punto en la list1 . También quiere la distancia (en metros) y el índice del punto (en la list1 ) para poder construir algunas reglas de negocio en torno a él; en esencia, estos son 2 nuevos cols que deben agregarse a la list1 ( near_dist , indx ).

Estoy usando la función gdist , pero no puedo hacer que esto funcione con entradas de marco de datos.

Ejemplo de listas de entrada:

list1 <- data.frame(longitude = c(80.15998, 72.89125, 77.65032, 77.60599, 72.88120, 76.65460, 72.88232, 77.49186, 72.82228, 72.88871), latitude = c(12.90524, 19.08120, 12.97238, 12.90927, 19.08225, 12.81447, 19.08241, 13.00984, 18.99347, 19.07990)) list2 <- data.frame(longitude = c(72.89537, 77.65094, 73.95325, 72.96746, 77.65058, 77.66715, 77.64214, 77.58415, 77.76180, 76.65460), latitude = c(19.07726, 13.03902, 18.50330, 19.16764, 12.90871, 13.01693, 13.00954, 12.92079, 13.02212, 12.81447), locality = c("A", "A", "B", "B", "C", "C", "C", "D", "D", "E"))


Créditos a Martin Harringa por esta solución para facilitar este camino cuando necesite realizar esta función recorriendo un marco de datos en el blog de Mark Needham

library(dplyr) df %>% rowwise() %>% mutate(newcolumn_distance = distHaversine(c(df$long1, df$lat1), c(df$long2, df$lat2)))

Probé usando las dos funciones distm y distHaversine por separado en muestras grandes de conjuntos de datos del mundo real, y distHaversine parece salir mucho más rápido que la función distm. Estoy sorprendido porque pensé que los dos eran simplemente la misma función en dos formatos.


Para calcular la distancia geográfica entre dos puntos con coordenadas de latitud / longitud, puede usar varias fórmulas. El paquete de geosphere tiene distCosine , distHaversine , distVincentySphere y distVincentyEllipsoid para calcular la distancia. De estos, distVincentyEllipsoid se considera el más preciso, pero es computacionalmente más intenso que los otros.

Con una de estas funciones, puede hacer una matriz de distancia. En función de esa matriz, puede asignar nombres de locality función de la distancia más corta con la que which.min y la distancia correspondiente con min (consulte la última parte de la respuesta) de esta manera:

library(geosphere) # create distance matrix mat <- distm(list1[,c(''longitude'',''latitude'')], list2[,c(''longitude'',''latitude'')], fun=distVincentyEllipsoid) # assign the name to the point in list1 based on shortest distance in the matrix list1$locality <- list2$locality[max.col(-mat)]

esto da:

> list1 longitude latitude locality 1 80.15998 12.90524 D 2 72.89125 19.08120 A 3 77.65032 12.97238 C 4 77.60599 12.90927 D 5 72.88120 19.08225 A 6 76.65460 12.81447 E 7 72.88232 19.08241 A 8 77.49186 13.00984 D 9 72.82228 18.99347 A 10 72.88871 19.07990 A

Otra posibilidad es asignar la locality función de los valores promedio de longitud y latitud de la locality s en la list2 :

library(dplyr) list2a <- list2 %>% group_by(locality) %>% summarise_each(funs(mean)) %>% ungroup() mat2 <- distm(list1[,c(''longitude'',''latitude'')], list2a[,c(''longitude'',''latitude'')], fun=distVincentyEllipsoid) list1 <- list1 %>% mutate(locality2 = list2a$locality[max.col(-mat2)])

o con data.table :

library(data.table) list2a <- setDT(list2)[,lapply(.SD, mean), by=locality] mat2 <- distm(setDT(list1)[,.(longitude,latitude)], list2a[,.(longitude,latitude)], fun=distVincentyEllipsoid) list1[, locality2 := list2a$locality[max.col(-mat2)] ]

esto da:

> list1 longitude latitude locality locality2 1 80.15998 12.90524 D D 2 72.89125 19.08120 A B 3 77.65032 12.97238 C C 4 77.60599 12.90927 D C 5 72.88120 19.08225 A B 6 76.65460 12.81447 E E 7 72.88232 19.08241 A B 8 77.49186 13.00984 D C 9 72.82228 18.99347 A B 10 72.88871 19.07990 A B

Como puede ver, esto conduce en la mayoría de los casos (7 de 10) a otra locality asignada.

Puedes agregar la distancia con:

list1$near_dist <- apply(mat2, 1, min)

u otro enfoque con max.col (que es muy probable más rápido):

list1$near_dist <- mat2[matrix(c(1:10, max.col(-mat2)), ncol = 2)] # or using dplyr list1 <- list1 %>% mutate(near_dist = mat2[matrix(c(1:10, max.col(-mat2)), ncol = 2)]) # or using data.table (if not already a data.table, convert it with ''setDT(list1)'' ) list1[, near_dist := mat2[matrix(c(1:10, max.col(-mat2)), ncol = 2)] ]

el resultado:

> list1 longitude latitude locality locality2 near_dist 1: 80.15998 12.90524 D D 269966.8970 2: 72.89125 19.08120 A B 65820.2047 3: 77.65032 12.97238 C C 739.1885 4: 77.60599 12.90927 D C 9209.8165 5: 72.88120 19.08225 A B 66832.7223 6: 76.65460 12.81447 E E 0.0000 7: 72.88232 19.08241 A B 66732.3127 8: 77.49186 13.00984 D C 17855.3083 9: 72.82228 18.99347 A B 69456.3382 10: 72.88871 19.07990 A B 66004.9900