Arshad Islam Arshad Islam - 29 days ago 9
R Question

Driving Distance from Lat Lng through Loop

I have a lattitude and longitude for two points in a dataframe. I am using the code below in R for obtaining the driving distance.

library(XML)
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)
}

test$origin1 = paste0("'",test$store_lat,",",test$store_lng,"'")
test$destination1 = paste0("'",test$lat,",",test$lng,"'")

distance <- list()
for(i in 1:nrow(test)){
dat <- latlon2ft(test[i,'origin1'],test[i,'destination1'])
distance[[i]] <- dat
}

all_distance <- do.call("rbind", distance)


But i am getting the following error.

Error in xpathApply(xmlfile, "//distance")[[1]] : subscript out of bounds
3 xmlChildren(xpathApply(xmlfile, "//distance")[[1]])
2 xmlValue(xmlChildren(xpathApply(xmlfile, "//distance")[[1]])$value)
1 latlon2ft(test[i, "origin1"], test[i, "destination1"])


This is a sample of my data:

store_lat | store_lng | lat | lng
19.21368 | 72.99034 | 19.1901094 | 72.9758546
19.10749 | 72.86444 | 19.1052534 | 72.8609213
19.01480 | 72.84545 | 18.9942502 | 72.8365256
19.01480 | 72.84545 | 19.1453449 | 72.8367015


Where in my code am i wrong? As far as i can see i am not able to pass the values correctly into the function while running the loop. But i am not able to find a work around. Thanks in advance for any help.

Answer Source

The subscript out of bounds error is occurring because you are not using the correct API format for the URL. It produces an xmlfile response from the Google server of:

<?xml version="1.0" encoding="UTF-8"?>
<DistanceMatrixResponse>
  <status>OK</status>
  <origin_address/>
  <destination_address/>
  <row>
    <element>
      <status>NOT_FOUND</status>
    </element>
  </row>
</DistanceMatrixResponse>

Which has no valid distance in it.

The mistake is the single quotes around the origins and destinations in the URL. When you join them together with the code

test$origin1 = paste0("'",test$store_lat,",",test$store_lng,"'")
test$destination1 = paste0("'",test$lat,",",test$lng,"'")

You add ' single quotes around the values, which is incorrect. If you drop the single quotes:

test$origin1 = paste0(test$store_lat,",",test$store_lng)
test$destination1 = paste0(test$lat,",",test$lng)

Your code then produces a correct URL of http://maps.googleapis.com/maps/api/distancematrix/xml?origins=19.21368,72.99034&destinations=19.1901094,72.9758546&mode=driving&sensor=false" without the single quotes. The resulting XML returned by the Google server is then:

<?xml version="1.0" encoding="UTF-8"?>
<DistanceMatrixResponse>
  <status>OK</status>
  <origin_address>External Bypass Rd, Laxmi Nagar, Balkum Pada, Majiwada, Thane, Maharashtra 400608, India</origin_address>
  <destination_address>A-5, Chhatraprati Sambhaji Rd, Ghantali, Thane West, Thane, Maharashtra 400602, India</destination_address>
  <row>
    <element>
      <status>OK</status>
      <duration>
        <value>981</value>
        <text>16 mins</text>
      </duration>
      <distance>
        <value>4908</value>
        <text>4.9 km</text>
      </distance>
    </element>
  </row>
</DistanceMatrixResponse>

Which now has a valid distance value.

You can find more details on the specifics of the Google Maps Distance API here