计算数据帧R中多个距离经度纬度

Arj*_*jan 6 r distance latitude-longitude

我不确定这是否是提出问题的正确位置(我是R和本网站的新手).我的问题如下:我如何计算经度和纬度点之间的距离?

我在这个网站上搜索了我的问题的答案,但答案只考虑了2分(而我的数据集包含超过207000行).

我有一个名为'adsb_relevant_columns_correct_timedifference'的数据框,其中包含以下列:Callsign,Altitude,Speed,Direction,Date_Time,Latitude,Longitude.

Callsign Altitude  Speed Direction   Date_Time             Latitude     Longitude
A118       18000    110  340         2017-11-06 22:28:09   70.6086      58.2959
A118       18500    120  339         2017-11-06 22:29:09   72.1508      58.7894
B222       18500    150  350         2017-11-08 07:28:09   71.1689      59.1234
D123       19000    150  110         2018-05-29 15:13:27   69.4523      68.1235
Run Code Online (Sandbox Code Playgroud)

我想计算每次测量之间的距离(以米为单位)(每行是一个新的测量值)并将其添加为一个名为"距离"的新列.第一次距离计算应该在第二行,因为以后的目的.因此,"距离"列的第一行可以是零或NA,这无关紧要.

所以,我想知道第一次测量(Lat 70.6086和Long 58.2959)与第二次测量(Lat 72.1508和58.7894)之间的距离.然后是第二次和第三次测量之间的距离.然后在第三和第四之间,依此类推,进行超过207000次测量.

预期的输出应该是这样的:

Callsign Altitude  Speed Direction   Date_Time             Latitude     Longitude  Distance 
A118       18000    110  340         2017-11-06 22:28:09   70.6086      58.2959    NA  
A118       18500    120  339         2017-11-06 22:29:09   72.1508      58.7894    172000
B222       18500    150  350         2017-11-08 07:28:09   71.1689      59.1234    110000
D123       19000    150  110         2018-05-29 15:13:27   69.4523      68.1235    387000
Run Code Online (Sandbox Code Playgroud)

我在R中找到了distm函数,我可以手动完成两次测量而不是完整的数据集.

distm(p1, p2, fun = distHaversine)
Run Code Online (Sandbox Code Playgroud)

我尝试了以下代码

adsb_relevant_columns_correct_timedifference <- mutate(adsb_relevant_columns_correct_timedifference, Distance =
distm(c(adsb_relevant_columns_correct_timedifference$Longitude, adsb_relevant_columns_correct_timedifference$Latitude),
      c(lag(adsb_relevant_columns_correct_timedifference$Longitude, adsb_relevant_columns_correct_timedifference$Latitude)), fun = distCosine))
Run Code Online (Sandbox Code Playgroud)

但是,我收到以下错误

mutate_impl(.data,dots)出错:评估错误:向量的长度错误,应为2.

对于我的长篇解释,我很抱歉,但我希望我的问题很明确.有人可以告诉我如何计算几个测量之间的距离,并将其作为新列添加到我的数据框中?

kat*_*ath 6

distm您可以使用distHaversine-function代替。在您的mutate通话中,您不应该重复数据框并使用$运算符,现在mutate已经可以在何处查找列。发生错误是因为您需要使用cbind而不是c, 因为c创建一个长向量,只需将列堆叠在一起,而cbind创建一个包含两列的数据框(在这种情况下您想要的)。

library(geosphere)
library(dplyr)

mutate(mydata, 
       Distance = distHaversine(cbind(Longitude, Latitude),
                                cbind(lag(Longitude), lag(Latitude))))

#   Callsign Altitude Speed Direction           Date_Time Latitude Longitude Distance
# 1     A118    18000   110       340 2017-11-06T22:28:09  70.6086   58.2959       NA
# 2     A118    18500   120       339 2017-11-06T22:29:09  72.1508   58.7894 172569.2
# 3     B222    18500   150       350 2017-11-08T07:28:09  71.1689   59.1234 109928.5
# 4     D123    19000   150       110 2018-05-29T15:13:27  69.4523   68.1235 387356.2
Run Code Online (Sandbox Code Playgroud)

使用distCosine它有点棘手,因为NA如果缺少输入纬度或经度之一,它不会返回。因此,我稍微修改了函数,这解决了问题:

modified_distCosine <- function(Longitude1, Latitude1, Longitude2, Latitude2) {
  if (any(is.na(c(Longitude1, Latitude1, Longitude2, Latitude2)))) {
    NA
  } else {
    distCosine(c(Longitude1, Latitude1), c(Longitude2, Latitude2))
  }
}

mutate(mydata, 
       Distance = mapply(modified_distCosine, 
                         Longitude, Latitude, lag(Longitude), lag(Latitude)))

#   Callsign Altitude Speed Direction           Date_Time Latitude Longitude Distance
# 1     A118    18000   110       340 2017-11-06T22:28:09  70.6086   58.2959       NA
# 2     A118    18500   120       339 2017-11-06T22:29:09  72.1508   58.7894 172569.2
# 3     B222    18500   150       350 2017-11-08T07:28:09  71.1689   59.1234 109928.5
# 4     D123    19000   150       110 2018-05-29T15:13:27  69.4523   68.1235 387356.2
Run Code Online (Sandbox Code Playgroud)

在这里,我使用参数mapply来应用修改后的函数Longitude, Latitude, lag(Longitude), lag(Latitude)
我很确定必须有一种更优雅的方式,但至少这是有效的。

数据

mydata <- structure(list(Callsign = c("A118", "A118", "B222", "D123"), 
                         Altitude = c(18000L, 18500L, 18500L, 19000L), 
                         Speed = c(110L, 120L, 150L, 150L), 
                         Direction = c(340L, 339L, 350L, 110L), 
                         Date_Time = c("2017-11-06T22:28:09", "2017-11-06T22:29:09", "2017-11-08T07:28:09", "2018-05-29T15:13:27"), 
                         Latitude = c(70.6086, 72.1508, 71.1689, 69.4523), 
                         Longitude = c(58.2959, 58.7894, 59.1234, 68.1235)), 
                    .Names = c("Callsign", "Altitude", "Speed", "Direction", "Date_Time", "Latitude", "Longitude"), 
                    class = "data.frame", row.names = c(NA, -4L))
Run Code Online (Sandbox Code Playgroud)