纬度/经度坐标的2个列表之间的地理距离
我有2个列表( list1
, list2
)与纬度/经度的各个位置。 一个列表( list2
)具有list1
没有的位置名称。
我也需要list1中每个点的近似位置。 所以我想在list1
取一个点,试着在list2
寻找最近的点,然后把这个地方。 我重复list1
每一点。 它也希望距离(以米为单位)和点的索引(在list1
),所以我可以围绕它创build一些业务规则 – 本质上这些是应该添加到list1
( near_dist
, near_dist
)的2个新near_dist
。
我正在使用gdist
函数,但我无法得到这与dataframeinput工作。
示例input列表:
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"))
要计算具有经度/纬度坐标的两点之间的地理距离,可以使用几个公式。 包地geosphere
包含用于计算距离的distCosine
, distHaversine
, distVincentySphere
和distVincentyEllipsoid
。 其中, distVincentyEllipsoid
被认为是最准确的,但在计算上比其他的更密集。
有了这些function之一,你可以做一个距离matrix。 基于这个matrix,你可以根据最短的距离,使用which.min
和相应的距离min
(参见答案的最后一部分)来分配locality
名称,如下所示:
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)]
这给了:
> 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
另一种可能性是根据列表2中的locality
的平均经度和纬度值来分配locality
:
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)])
或用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)] ]
这给了:
> list1 longitude latitude locality locality2 1 80.15998 12.90524 DD 2 72.89125 19.08120 AB 3 77.65032 12.97238 CC 4 77.60599 12.90927 DC 5 72.88120 19.08225 AB 6 76.65460 12.81447 EE 7 72.88232 19.08241 AB 8 77.49186 13.00984 DC 9 72.82228 18.99347 AB 10 72.88871 19.07990 AB
正如你所看到的,这导致大部分(十分之七)的场合到另一个指定的locality
。
您可以添加距离:
list1$near_dist <- apply(mat2, 1, min)
或另一种方法max.col
(很可能更快):
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)] ]
结果:
> list1 longitude latitude locality locality2 near_dist 1: 80.15998 12.90524 DD 269966.8970 2: 72.89125 19.08120 AB 65820.2047 3: 77.65032 12.97238 CC 739.1885 4: 77.60599 12.90927 DC 9209.8165 5: 72.88120 19.08225 AB 66832.7223 6: 76.65460 12.81447 EE 0.0000 7: 72.88232 19.08241 AB 66732.3127 8: 77.49186 13.00984 DC 17855.3083 9: 72.82228 18.99347 AB 69456.3382 10: 72.88871 19.07990 AB 66004.9900