【问题标题】:Calculating the distance between points in different data frames计算不同数据帧中点之间的距离
【发布时间】:2015-10-24 07:46:38
【问题描述】:

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

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

我设想最终的函数类似于 A$Name=B$Name 然后使用它们对应的纬度/经度数据来计算它们之间的距离。

有什么想法吗?

示例数据:

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 使用它们对应的经纬度数据,它们之间的距离是多少。

我还应该注意,我将无法进行简单的欧几里德距离,因为这些点出现在水中,并且它们之间的路径距离需要在水中(或以某个区域为界)。对此的任何帮助也将不胜感激。

【问题讨论】:

  • 您应该想出一个MRE 来展示您的输入和所需的输出。看起来您想合并一列,然后计算距离。合并将是关键。

标签: r dataframe distance latitude-longitude


【解决方案1】:

要计算纬度/经度点之间的距离,您可以使用 geosphere 包中的 distm 函数。在此函数中,您可以使用几个公式来计算距离: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

【讨论】:

    【解决方案2】:

    如果没有可重现的例子,我所能做的就是为您提供一个通用的解决方案。

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

    我将首先创建两个符合您的一般描述的data.tables:

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

    现在,我们想通过Name 合并AB(要合并,我们需要一个key 集合,我已经很方便地完成了),然后使用各自的x 和@ 987654330@坐标来计算(欧几里得)距离。这样做很简单:

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

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

    如果AB 已经存储为data.frames,则从头开始,这并不复杂:

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

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

    *设置B的密钥可能不是绝对必要的,但我认为这样做是个好习惯。另外,setDTkey 选项目前仅在data.table (1.9.5+) 的开发版本中可用;使用 CRAN 版本,使用setkey(setDT(A),Name)等。

    【讨论】:

      猜你喜欢
      • 2020-11-23
      • 1970-01-01
      • 2021-05-25
      • 2014-11-29
      • 1970-01-01
      • 2017-04-11
      • 1970-01-01
      • 1970-01-01
      • 2014-02-28
      相关资源
      最近更新 更多