使用R和Google地图API获取两点(纬度,经度)之间的驾驶距离

16

我想要获取给定经纬度的两个点之间的驾车距离。我可以手动将它们放入 Google Maps 中并获取驾车距离,但我希望通过编程实现。

我猜 JavaScript 是解决方案。但是,我不懂 JavaScript,我相当熟悉使用 R。因为我所有的数据分析都是在 R 中进行的,所以我更喜欢用 R 实现。

我需要的是沿着道路的距离而不是直线距离。试了几个小时后,我在 R 中编写了以下函数(这篇文章这篇文章 帮了我不少)。你有更好的方法来获取距离吗?可能是在这个函数内部或者更简单的方法。

library(XML)
latlon2ft <- function(origin,destination)
{

xml.url <- paste0('http://maps.googleapis.com/maps/api/distancematrix/xml?origins=',origin,'&destinations=',destination,'&mode=driving&sensor=false')

xmlfile <- xmlTreeParse(xml.url)
xmltop = xmlRoot(xmlfile)
distance <- xmltop[['row']][[1]][5][1][['distance']][['value']][[1]]
distance <- as.numeric(unclass(distance)[['value']])
ft <- distance*3.28084 # FROM METER TO FEET
return(ft)
}

latlon2ft(origin='37.193489,-121.07395',destination='37.151616,-121.046586')

结果 = 17224.41


1
你看过这里的粉色框吗:https://developers.google.com/maps/documentation/distancematrix/#Limits? - barryhunter
5个回答

14

我编写了gmapsdistance包来实现这一点。它可以在CRAN上找到。您可以按照以下方式使用该函数:

results = gmapsdistance(origin = "38.1621328+24.0029257",
                        destination = "37.9908372+23.7383394",
                        mode = "walking") results
# $Time
# [1] 30025
# 
# $Distance
# [1] 39507
# 
# $Status
# [1] "OK"

您还可以包含起点和终点向量,并获取结果距离矩阵。它还支持方向,并有许多选项:

results = gmapsdistance(origin = c("Washington+DC", "New+York+NY", "Seattle+WA", "Miami+FL"), 
                        destination = c("Los+Angeles+CA", "Austin+TX", "Chicago+IL", "Philadelphia+PA"), 
                        mode = "bicycling", 
                        departure = 1514742000)
results
# $Time
#              or Time.Los+Angeles+CA Time.Austin+TX Time.Chicago+IL Time.Philadelphia+PA
# 1 Washington+DC              856621         535146          247765                54430
# 2   New+York+NY              917486         596011          308630                32215
# 3    Seattle+WA              374692         678959          674989               956702
# 4      Miami+FL              829039         416667          452035               411283
# 
# $Distance
#              or Distance.Los+Angeles+CA Distance.Austin+TX Distance.Chicago+IL Distance.Philadelphia+PA
# 1 Washington+DC                 4567470            2838519             1303067                   266508
# 2   New+York+NY                 4855086            3126136             1590684                   160917
# 3    Seattle+WA                 1982354            3562970             3588297                  5051951
# 4      Miami+FL                 4559205            2279966             2381610                  2169382
# 
# $Status
#              or status.Los+Angeles+CA status.Austin+TX status.Chicago+IL status.Philadelphia+PA
# 1 Washington+DC                    OK               OK                OK                     OK
# 2   New+York+NY                    OK               OK                OK                     OK
# 3    Seattle+WA                    OK               OK                OK                     OK
# 4      Miami+FL                    OK               OK                OK                     OK

11
您需要在此处使用RCurl或等效工具。
library(XML)
library(bitops)
library(RCurl)
latlon2ft <- function(origin,destination){
  xml.url <- paste0('http://maps.googleapis.com/maps/api/distancematrix/xml?origins=',origin,'&destinations=',destination,'&mode=driving&sensor=false')
  xmlfile <- xmlParse(getURL(xml.url))
  dist <- xmlValue(xmlChildren(xpathApply(xmlfile,"//distance")[[1]])$value)
  distance <- as.numeric(sub(" km","",dist))
  ft <- distance*3.28084 # FROM METER TO FEET
  return(ft)
}

latlon2ft(origin='37.193489,-121.07395',destination='37.151616,-121.046586')

结果:

[1] 17224.41

2
请注意,就像谷歌地图一样,这个程序可以接受几乎任何形式的地址:邮政编码、完整地址、部分地址等等。Thomas,你的解决方案让我感到非常开心,谢谢!现在我只需要微调一下,让它能够输出小时数的持续时间即可。 - Waldir Leoncio
你的每日请求次数已经达到上限了吗? - Thomas
是的,我刚发现这个问题并删除了我的评论。我将重新编写代码以最小化查询。;) - Waldir Leoncio
顺便提一下,如果你想要用英里和英尺来表示,你也可以在 xml.url 的末尾加上 units=imperial 参数。 - Waldir Leoncio

4

我需要计算一堆地址之间的驾驶距离,所以我写了一个简短的函数,并将其放入了一个类似的小数据包中。你可以在我的GitHub存储库中找到它:https://github.com/JanMultmeier/GeoData/blob/master/GeoDataPackage/R/GetDist.R

按照以下步骤运行它:

require(devtools)
install_github("JanMultmeier/GeoData/GeoDataPackage")
library(GeoData)
getDist(from="1 Infinity Loop, Cupertino, CA 95014", to="1600 Amphitheatre Pkwy, Mountain View, CA 94043",modus="driving",get="distance")

它应该返回14.8公里。

Barryhunter已经暗示了Google的使用限制,将此API的使用与在Google地图上显示结果绑定。

希望这仍然可以帮助一些偶然发现这篇文章的人(像我一样)…


2
写作时,Renjin(一种基于Java的R解释器)没有很多包来帮助解决这个问题。以下是一种不依赖额外包的实现方法。
# Computes the distance between two locations in meters. This uses an online
# map API and therefore an Internet connection is required for an accurate
# result. If no connection is found, this will use the Haversine formula
# to provide a rough estimate for the distance.
#
# @param src The source latitude and longitude.
# @param dst The destination latitude and longitude.
# @param mode Driving, cycling, walking, etc.
distance <- function( lat1, lon1, lat2, lon2, mode = 'driving' ) {
  lat1 = as.numeric( lat1 )
  lon1 = as.numeric( lon1 )
  lat2 = as.numeric( lat2 )
  lon2 = as.numeric( lon2 )

  # Create the URL to use to get the distance data.
  url = paste0(
    'https://maps.googleapis.com/maps/api/distancematrix/xml?',
    'origins=', lat1,
    ',', lon1,
    '&destinations=', lat2,
    ',', lon2,
    '&mode=', mode,
    '&sensor=false'
  )

  tryCatch({
    # Download the XML document with distance information.
    xml = readLines( url )

    # The <value> element immediately follows the distance element.
    value = xml[ grep( "<distance>", xml ) + 1 ]

    # Obtain the distance in meters.
    meters = sub( ".*>(.*?)<.*", "\\1", value )

    # Return the distance.
    as.numeric( meters )
  },
  warning = function( w ) {
    haversine( lat1, lon1, lat2, lon2 )
  },
  error = function( e ) {
    haversine( lat1, lon1, lat2, lon2 )
  })
}

# Computes distance using Haversine formula.
#
# Returns the result in meters.
haversine <- function( lat1, lon1, lat2, lon2, radius = 6371 ) {
  # Convert decimal degrees to radians
  lon1 = lon1 * pi / 180
  lon2 = lon2 * pi / 180
  lat1 = lat1 * pi / 180
  lat2 = lat2 * pi / 180

  # Haversine formula
  dlon = lon2 - lon1
  dlat = lat2 - lat1
  a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
  c = 2 * atan2(sqrt(a), sqrt(1-a))

  return( radius * c * 1000 )
}

输出:

distance( '44.5646', '-123.2620', '41.2861', '-124.0902' )
[1] 495892
distance( 44.5646, -123.2620, 41.2861, -124.0902, mode='walking' )
[1] 487715

将米转换为英尺是读者的一项练习。


0
我已经编写了googleway包,使用Google Maps API来完成此任务。
特别是,google_directions()函数将为您提供驾车距离,方向,路线,腿部,步骤等信息。 而google_distance()函数将为您提供所有起始点/目的地的距离矩阵。
您需要一个Google API密钥才能使用他们的API。
library(googleway)

## your valid API key
key <- "your_api_key_here"

directions <- google_directions(origin = c(37.193489,-121.07395),
                                destination = c(37.151616,-121.046586),
                                key = key, 
                                simplify = T)

directions$routes$legs
# [[1]]
# distance.text distance.value duration.text duration.value duration_in_traffic.text duration_in_traffic.value                 end_address
# 1        5.2 km           5250        3 mins            161                   3 mins                       156 I-5, Gustine, CA 95322, USA
# end_location.lat end_location.lng               start_address start_location.lat start_location.lng
# 1         37.15162        -121.0466 I-5, Gustine, CA 95322, USA           37.19349           -121.074
# steps
# 1 5.2 km, 5250, 3 mins, 161, 37.1516163, -121.0465852, Head <b>southeast</b> on <b>I-5 S</b>, ij_bFfg~aVpBgA`DkB~FeDbIwEpEgCtaAsj@nAs@lDqBxIaF~FgDlHcEjC{AdFuCrBkAhC{A|A{@|A}@bAk@rBkArBkA|A{@`DiB|A}@vDwBdAm@dAm@rBkA|A{@zA{@~J{FpC_B~A}@tBkAjHeEvGuDlMmHtBkAVO, 37.1934864, -121.0739565, DRIVING
#   traffic_speed_entry via_waypoint
#   1                NULL         NULL



google_distance(origins = list(c(37.193489,-121.07395)),
                destinations = list(c(37.151616,-121.046586)),
                key = key, 
                simplify = T,
                units = "imperial")

# $destination_addresses
# [1] "I-5, Gustine, CA 95322, USA"
# 
# $origin_addresses
# [1] "I-5, Gustine, CA 95322, USA"
# 
# $rows
# elements
# 1 3.3 mi, 5250, 3 mins, 161, 3 mins, 157, OK
# 
# $status
# [1] "OK"

给定 google_directions() 函数返回一条折线(当你在 Google 地图上搜索路线时所得到的线路),我们可以将其绘制在 Google 地图上。

key <- 'your_map_api_key'

df_route <- decode_pl(directions$routes$overview_polyline$points)

google_map(data = df_route, key = key, height = 800, search_box = T) %>%
    add_markers()
## or you can use `add_polyline()` to view the entire line

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接