2 个经纬度点列表(坐标)之间的地理/地理空间距离 [英] Geographic / geospatial distance between 2 lists of lat/lon points (coordinates)

查看:38
本文介绍了2 个经纬度点列表(坐标)之间的地理/地理空间距离的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有 2 个列表(list1list2),其中包含各个位置的纬度/经度.一个列表 (list2) 具有 list1 没有的位置名称.

我还想要 list1 中每个点的近似位置.所以我想在 list1 中取一个点,尝试在 list2 中寻找最近的点并取那个位置.我对 list1 中的每一点重复.它还需要距离(以米为单位)和点的索引(在 list1 中),以便我可以围绕它构建一些业务规则 - 基本上这些是应该添加到 的 2 个新列list1 (near_dist, indx).

我正在使用 gdist 函数,但我无法让它与数据框输入一起工作.

示例输入列表:

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),纬度 = 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),纬度 = 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 包有 distCosinedistHaversinedistVincentySpheredistVincentyEllipsoid 用于计算距离.其中,distVincentyEllipsoid 被认为是最准确的,但在计算上比其他的更密集.

使用这些函数之一,您可以制作距离矩阵.根据该矩阵,您可以根据 which.min 的最短距离和 min 的相应距离分配 locality 名称(请参阅此答案的最后一部分)像这样:

图书馆(地理圈)# 创建距离矩阵mat <- distm(list1[,c('longitude','latitude')], list2[,c('longitude','latitude')], fun=distVincentyEllipsoid)# 根据矩阵中的最短距离为list1中的点指定名称list1$locality <- list2$locality[max.col(-mat)]

这给出:

<块引用>

>列表1经度纬度1 80.15998 12.905242 72.89125 19.081203 77.65032 12.97238 摄氏度4 77.60599 12.909275 72.88120 19.082256 76.65460 12.81447 东7 72.88232 19.082418 77.49186 13.009849 72.82228 18.9934710 72.88871 19.07990

<小时>

另一种可能是根据list2locality的平均经纬度值来分配locality:

库(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)] ]

这给出:

<块引用>

>列表1经度纬度 locality locality21 80.15998 12.90524 D D2 72.89125 19.08120 A B3 77.65032 12.97238 C C4 77.60599 12.90927 直流5 72.88120 19.082256 76.65460 12.81447 东东7 72.88232 19.08241 A B8 77.49186 13.00984 直流9 72.82228 18.9934710 72.88871 19.07990

如您所见,这在大多数情况下(10 次中有 7 次)会导致另一个指定的locality.

<小时>

您可以添加距离:

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

或使用 max.col 的另一种方法(很可能更快):

list1$near_dist <- mat2[matrix(c(1:10, max.col(-mat2)), ncol = 2)]# 或使用 dplyrlist1 <- list1 %>% mutate(near_dist = mat2[matrix(c(1:10, max.col(-mat2)), ncol = 2)])# 或使用 data.table (如果还不是 data.table,用 'setDT(list1)' 转换它)list1[, near_dist := mat2[matrix(c(1:10, max.col(-mat2)), ncol = 2)] ]

结果:

<块引用>

>列表1经度纬度 locality locality2 near_dist1: 80.15998 12.90524 D D 269966.89702:72.89125 19.08120 A B 65820.20473: 77.65032 12.97238 C C 739.18854: 77.60599 12.90927 直流 9209.81655:72.88120 19.08225 A B 66832.72236:76.65460 12.81447 EE 0.00007: 72.88232 19.08241 A B 66732.31278: 77.49186 13.00984 直流 17855.30839: 72.82228 18.99347 A B 69456.338210: 72.88871 19.07990 A B 66004.9900

I have 2 lists (list1, list2) with latitude / longitudes of various locations. One list (list2) has locality names that list1 does not have.

I want an approximate locality for every point in list1 as well. So I want to take a point in list1, try to look for the nearest point in list2 and take that locality. I repeat for every point in list1. It also want the distance (in meters) and the index of the point (in list1) so I can build some business rules around it - essentially these are 2 new cols that should be added to list1 (near_dist, indx).

I am using the gdist function, but I'm unable to get this to work with data frame inputs.

Example input lists:

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"))

解决方案

To calculate the geographic distance between two points with latitude/longitude coordinates, you can use several formula's. The package geosphere has the distCosine, distHaversine, distVincentySphere and distVincentyEllipsoid for calculating the distance. Of these, the distVincentyEllipsoid is considered the most accurate one, but is computationally more intensive than the other ones.

With one of these functions, you can make a distance matrix. Based on that matrix you can then assign locality names based on shortest distance with which.min and the corresponding distance with min (see for this the last part of the answer) like this:

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)]

this gives:

> 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


Another possibility is to assign the locality based on the average longitude and latitude values of the localitys in 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)])

or with 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)] ]

this gives:

> 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

As you can see, this leads in most (7 out of 10) occasions to another assigned locality.


You can add the distance with:

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

or another approach with max.col (which is highly probable faster):

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)] ]

the result:

> 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

这篇关于2 个经纬度点列表(坐标)之间的地理/地理空间距离的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆