我试图找到两个不同数据帧中点之间的距离,因为它们在其中一列中具有相同的值。
我认为第一步是加入或关联两个数据帧中的数据。例如,数据框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"))
现在我要关联A
和B
,以便我可以询问最终问题A$Name==B$Name
使用相应的lat长数据,它们之间的距离是多少。
我还应该注意,我不能做一个直接的欧几里德距离,因为这些点出现在水中,它们之间的路径距离需要在水中(或由某个区域限制)。任何帮助也将受到赞赏。
答案 0 :(得分:3)
要计算纬度/经度点之间的距离,您可以使用distm
包中的geosphere
函数。在此功能中,您可以使用多个公式来计算距离:distCosine
,distHaversine
,distVincentySphere
和distVincentyEllipsoid
。最后一个被认为是最准确的一个(根据包裹作者)。
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")
现在,我们要将A
和B
合并到Name
(要合并,我们需要一个key
集合,我已经方便地完成了这个集合,然后使用相应的x
和y
坐标来计算(欧几里德)距离。这样做很简单:
A[B,distance:=sqrt(x^2+y^2)]
您寻找的距离现在存储在data.table
列下的A
distance
中。如果您不想存储距离,只想要输出,则可以执行:A[B,sqrt(x^2+y^2)]
。
如果A
和B
已经存储为data.frame
,那么要从头开始,这并不复杂:
setDT(A,key="Name")[setDT(B,key="Name"),distance:=sqrt(x^2+y^2)]
我们已使用方便的setDT
函数将A
和B
(内联)转换为data.table
引用,同时声明key
为Name
为*。
*设置B
的密钥可能不是绝对必要的,但我认为这样做是好的做法。此外,key
的{{1}}选项目前仅在setDT
(data.table
)的开发版中提供;使用CRAN版本,使用1.9.5+
等