计算不同数据帧中点之间的距离

时间:2015-08-01 21:23:07

标签: r dataframe distance latitude-longitude

我试图找到两个不同数据帧中点之间的距离,因为它们在其中一列中具有相同的值。

我认为第一步是加入或关联两个数据帧中的数据。例如,数据框A和B都包含纬度/经度信息,它们共享列Name。请注意,对于给定的名称,每个数据帧中的纬度/经度信息是不同的。这就是为什么我想计算它们之间的距离。

我设想最终函数类似if A$Name=B$Name然后使用相应的lat / long数据来计算它们之间的距离。

有什么想法吗?

示例数据:

A <- data.frame(Lat=1:4,Long=1:4,Name=c("a","b","c","d"))
B <- data.frame(Lat=5:8,Long=5:8,Name=c("a","b","c","d"))

现在我要关联AB,以便我可以询问最终问题A$Name==B$Name使用相应的lat长数据,它们之间的距离是多少。

我还应该注意,我不能做一个直接的欧几里德距离,因为这些点出现在水中,它们之间的路径距离需要在水中(或由某个区域限制)。任何帮助也将受到赞赏。

2 个答案:

答案 0 :(得分:3)

要计算纬度/经度点之间的距离,您可以使用distm包中的geosphere函数。在此功能中,您可以使用多个公式来计算距离:distCosinedistHaversinedistVincentySpheredistVincentyEllipsoid。最后一个被认为是最准确的一个(根据包裹作者)。

library(geosphere)

A <- data.frame(Lat=1:4, Long=1:4, Name=c("a","b","c","d"))
B <- data.frame(Lat=5:8, Long=5:8, Name=c("a","b","c","d"))

A$distance <- distVincentyEllipsoid(A[,c('Long','Lat')], B[,c('Long','Lat')])

这给出了:

> A
  Lat Long Name distance
1   1    1    a 627129.5
2   2    2    b 626801.7
3   3    3    c 626380.6
4   4    4    d 625866.6

请注意,您必须按照第一个经度和纬度的顺序包含纬度/经度列。

虽然这在这个简单的例子中非常有效,但在名称不相同的较大数据集中,这会导致问题。在这种情况下,您可以使用data.table并设置键,以便您可以匹配点并计算距离(正如@MichaelChirico在答案中所做的那样):

library(data.table)
A <- data.table(Lat=1:4, Long=1:4, Name=c("a","b","c","d"), key="Name")
B <- data.table(Lat=8:5, Long=8:5, Name=c("d","c","b","a"), key="Name")

A[B,distance:=distVincentyEllipsoid(A[,.(Long,Lat)], B[,.(Long,Lat)])]

如您所见,这给出了与前一种方法相同的正确结果(即相同):

> A
   Lat Long Name distance
1:   1    1    a 627129.5
2:   2    2    b 626801.7
3:   3    3    c 626380.6
4:   4    4    d 625866.6

要查看key="Name"的作用,请比较以下两个数据表:

B1 <- data.table(Lat=8:5, Long=8:5, Name=c("d","c","b","a"), key="Name")
B2 <- data.table(Lat=8:5, Long=8:5, Name=c("d","c","b","a"))

另请参阅this answer以获取更详细的示例。

答案 1 :(得分:2)

如果没有可重复的示例,我所能做的只是为您提供一般解决方案。

我喜欢data.table,这里的语法看起来很简单。查看Getting Started小插图,了解有关该软件包的更多信息。

我将首先创建两个与您的一般描述匹配的data.table

library(data.table)
set.seed(1734)
A<-data.table(Name=1:10,x=rnorm(10),key="Name")
B<-data.table(Name=1:10,y=rnorm(10),key="Name")

现在,我们要将AB合并到Name(要合并,我们需要一个key集合,我已经方便地完成了这个集合,然后使用相应的xy坐标来计算(欧几里德)距离。这样做很简单:

A[B,distance:=sqrt(x^2+y^2)]

您寻找的距离现在存储在data.table列下的A distance中。如果您不想存储距离,只想要输出,则可以执行:A[B,sqrt(x^2+y^2)]

如果AB已经存储为data.frame,那么要从头开始,这并不复杂:

setDT(A,key="Name")[setDT(B,key="Name"),distance:=sqrt(x^2+y^2)]

我们已使用方便的setDT函数将AB(内联)转换为data.table 引用,同时声明keyName为*。

*设置B的密钥可能不是绝对必要的,但我认为这样做是好的做法。此外,key的{​​{1}}选项目前仅在setDTdata.table)的开发版中提供;使用CRAN版本,使用1.9.5+