2013-05-31 19 views
14

Próbuję uzyskać odległość jazdy między dwoma punktami z podaną lat/lon. Mogę ręcznie umieścić je w mapie google i uzyskać odległość jazdy, ale chcę zrobić to wszystko programowo.Uzyskanie odległości jazdy między dwoma punktami (łac, lon) za pomocą R i interfejsu API Google Map

Domyślam się, że to język JavaScript. Ale, nie znam JavaScriptu i jestem dość obeznany z R. R. Wolałbym zrobić to w R, ponieważ robię całą analizę danych w R.

Szukam odległości wzdłuż drogi, a nie w locie dystans. Po kilku godzinach próbowałem napisałem następującą funkcję w R (This i this one). Czy masz lepszy sposób na uzyskanie dystansu w ramach tej funkcji lub czegokolwiek bardzo prostszego?

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

WYNIK = 17224,41

+1

Czy przeczytałeś tutaj różowe pole: https://developers.google.com/maps/documentation/distancematrix/#Limits? – barryhunter

+0

Ouch! Czy masz inny akceptowalny sposób uzyskania tego, czego potrzebuję? –

Odpowiedz

7

Trzeba RCurl lub odpowiednik tutaj.

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

Wynik:

[1] 17224.41 
+1

Zauważ, że podobnie jak Google Maps, zajmie to prawie każdą formę adresu, na który możesz rzucić: Kod pocztowy, pełne adresy, częściowe adresy ... Rozwiązanie sprawiło, że mój dzień, Thomas, dziękuję! Teraz muszę go zmodyfikować, aby uzyskać czas trwania w ciągu kilku godzin. –

+0

Czy udało Ci się maksymalnie wykorzystać codzienne żądania? – Thomas

+0

Tak, zrobiłem, właśnie się o tym dowiedziałem i skasowałem później mój komentarz. Po prostu przerobię mój kod, aby zminimalizować zapytania. ;) –

3

Potrzebowałem do obliczenia odległości jazdy na pęczek adresów, więc napisałem krótką funkcję i umieścić go w podobnie małym opakowaniu. Można go znaleźć w moim GitHub repo: https://github.com/JanMultmeier/GeoData/blob/master/GeoDataPackage/R/GetDist.R

Należy go uruchomić:

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

Należy zwrócić 14.8 km.

Barryhunter zasugerował już ograniczenie użytkowania przez Google, które wiąże wykorzystanie tego API do wyświetlania wyników na mapie Google.

nadzieja, że ​​nadal pomaga kilka osób, które natknąć tego postu (jak ja) ...

3

ja autorem pakiet gmapsdistance właśnie do tego. Jest dostępny w CRAN. Można użyć funkcji w następujący sposób:

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

można również obejmują wektory pochodzenia i przeznaczenia, i uzyskać wynikowy macierz odległości. Obsługuje również kierunki i ma kilka opcji:

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 
1

Pisałem pakiet googleway to zrobić przy użyciu Google Maps API

W szczególności, funkcja google_directions() dadzą Ci dystansach jeździsz, kierunki , trasy, nogi, schody itp. a funkcja google_distance() dadzą Ci macierz odległości dla wszystkich krajów pochodzenia/docelowych

Potrzebny jest klucz API Google, aby korzystać z ich 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`[email protected]@lDqBxIaF~FgDlHcEjC{AdFuCrBkAhC{A|A{@|A}@[email protected]|A{@`DiB|A}@[email protected]@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" 

Biorąc pod uwagę funkcję google_directions() zwraca łamaną (linia dostać w Mapach Google podczas wyszukiwania trasy), możemy wykreślić go na Google Map

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

0

W czasie pisania, Renjin (tłumacz Java R) nie ma wielu pakietów, aby rozwiązać ten problem. Oto implementacja, która nie zależy od dodatkowych pakietów.

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

wyjściowa:

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

Konwersja z metrów na stopy jest ćwiczeniem dla czytelnika.

Powiązane problemy