创建具有测地距离的新列

时间:2015-06-05 20:31:33

标签: r haversine

如何在数据框中添加一个新列,其中包含每个观察点的测地距离?我的数据框中的行是对雇用的汽​​车的观察,包括起点(经度+纬度)和行程的终点(经度+纬度)。

使用以下R函数计算测地距离:

haversine<- function(long1, lat1, long2, lat2) {

  stopifnot(is.numeric(long1),
            is.numeric(lat1),
            is.numeric(long2),
            is.numeric(lat2),
            long1 > -180,
            long1 < 180,
            lat1 > -180,
            lat1 < 180,
            long2 > -180,
            long2 < 180,
            lat2 > -180,
            lat2 < 180  
    )

  long1 <- long1*pi/180
  lat1 <- lat1*pi/180
  long2 <- long2*pi/180
  lat2 <- lat2*pi/180

  R <- 6371 # Earth mean radius [km]
  delta.long <- (long2 - long1)
  delta.lat <- (lat2 - lat1)
  a <- sin(delta.lat/2)^2 + cos(lat1) * cos(lat2) * sin(delta.long/2)^2
  c <- 2 * asin(min(1,sqrt(a)))
  d = R * c
  return(d) # Distance in km
}

使用此公式可以计算距离:

distance <- haversine(longitude1,latitude1,longitude2,latitude2)

由于我的数据框包含超过100,000个观测值,我想在我的数据框中添加一列,其中包括汽车旅行的所有测地距离。

我试过了: df["GeoDist"] <- haversine(LongitudeStart, LatitudeStart, LongitudeEnd, LatitudeEnd)

这导致了一个额外的列,但是在该列中所有距离都为零。当我用前面的公式手动计算它们时,这些距离不为零。

2 个答案:

答案 0 :(得分:1)

您可以使用 geosphere 包中的distHaversine()。或者,要获得更准确的结果,请使用distVincentyEllipsoid()。 (两个函数都以度为单位坐标,以米为单位返回距离。)

## Example data representing voyages of 1 and 2 degrees directly north from equator.
df <- data.frame(x_begin = c(0,0), y_begin = c(0,0), 
                 x_end   = c(0,0), y_end   = c(1,2))

library(geosphere)
distHaversine(df[, 1:2],  df[, 3:4])        ## Assumes a spherical Earth
# [1] 111319.5 222639.0
distVincentyEllipsoid(df[,1:2],  df[,3:4])  ## Much more accurate*
## [1] 110574.4 221149.5

## * According to Wikipedia, 1 degree of latitude at equator == 110.574 km 
## (http://en.wikipedia.org/wiki/Longitude#Length_of_a_degree_of_longitude)

答案 1 :(得分:0)

您需要mapply,因为您正在传递矢量参数。

# reproducible example
# 38.8895° N,  77.0352° W  # 
# 47.6204° N, 122.3491° W  # washington monument to space needle
# 40.6892° N,  74.0444° W  # 
# 37.8197° N, 122.4786° W  # statue of liberty to golden gate bridge
df <- data.frame(y1=c(  38.8895,  40.6892),
                 x1=c( -77.0352, -74.0444),
                 y2=c(  47.6204, 37.8197 ),
                 x2=c( -122.3491,-122.4786 ))

with(df, mapply(haversine, lat1=y1, long1=x1, lat2=y2, long2=x2) )
# [1] 3738.587 4129.629 # looks right to me