简体   繁体   English

使用R和Google Map API获取两点之间的距离(lat,lon)

[英]Getting driving distance between two points (lat, lon) using R and Google Map API

I am trying to get the driving distance between two points with lat/lon given. 我试图通过给出lat / lon来获得两点之间的行驶距离。 I can manually put them into google map and get the driving distance but I want to do all this programatically. 我可以手动将它们放入谷歌地图并获得驾驶距离,但我想以编程方式完成所有这些操作。

I guess JavaScript is the language to go. 我想JavaScript是最常用的语言。 But, I do not know JavaScript and I am fairly familiar using R. I would prefer to do it in R since I am doing all the data analysis in R. 但是,我不知道JavaScript,我相当熟悉使用R.我更喜欢在R中这样做,因为我在R中进行所有数据分析。

I am looking for distance along the road not crow-fly distance. 我正在寻找沿着道路的距离而不是飞行距离。 After few hours of trying, I wrote the following function in R ( This and this one helped). 经过几个小时的尝试,我在R中编写了以下函数( 这个这一个帮助)。 Do you have any better way to get the distance either within this function or anything very very simpler? 你有没有更好的方法来获得这个功能或任何非常简单的距离?

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

RESULT = 17224.41 结果= 17224.41

You need RCurl or an equivalent here. 你需要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')

Result: 结果:

[1] 17224.41

I authored the gmapsdistance package to do just that. 我创作了gmapsdistance包来做到这一点。 It is available on CRAN. 它可以在CRAN上使用。 You can use the function in the following way: 您可以通过以下方式使用该功能:

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

You can also include vectors of origins and destinations, and get the resulting distance matrix. 您还可以包含原点和目的地的矢量,并获得生成的距离矩阵。 It supports also directions, and has a bunch of options: 它还支持方向,并有一堆选项:

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

I needed to calculate driving distances for a bunch of addresses, so I wrote a short function for it and put it in a likewise small packet. 我需要计算一堆地址的行驶距离,所以我为它编写了一个简短的函数并将其放入同样小的数据包中。 You can find it in my GitHub repo: https://github.com/JanMultmeier/GeoData/blob/master/GeoDataPackage/R/GetDist.R 你可以在我的GitHub回购中找到它: https//github.com/JanMultmeier/GeoData/blob/master/GeoDataPackage/R/GetDist.R

This should get it to run: 这应该让它运行:

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

It should return 14.8 km. 它应该返回14.8公里。

Barryhunter has already hinted at the usage restriction by Google, which ties the use of this API to displaying the results on a Google map. Barryhunter已经暗示谷歌的使用限制,将此API的使用与在Google地图上显示结果联系起来。

Hope that still helps some people who stumble across this post (like me)... 希望这仍然可以帮助一些偶然发现这篇文章的人(像我一样)......

I've written the googleway package to do this using Google Maps API 我已经使用Google Maps API编写了googleway程序包

In particular, the google_directions() function will give you driving distances, directions, routes, legs, steps etc. And the google_distance() function will give you a distance matrix for all the origins/destinations 特别是, google_directions()函数将为您提供行车距离,路线,路线,腿,步等。而google_distance()函数将为您提供所有起点/目的地的距离矩阵

You need a Google API key to use their API 您需要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"

Given the google_directions() function returns a polyline (the line you get on Google Maps when you search for a route), we can plot it on a Google Map 鉴于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

在此输入图像描述

At time of writing, Renjin (a Java-based R interpreter) does not have a lot of packages to help solve this problem. 在撰写本文时, Renjin (一个基于Java的R解释器)没有很多软件包来帮助解决这个问题。 Here is an implementation that does not depend on extra packages. 这是一个不依赖于额外包的实现。

# 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 )
}

Output: 输出:

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

Conversion from meters to feet is an exercise for the reader. 从米到英尺的转换是读者的练习。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM