R代码gmapsdistance [英] R Code gmapsdistance

查看:73
本文介绍了R代码gmapsdistance的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码用于查找两个位置之间的旅行时间.我正在使用vba调用脚本,这就是为什么args命令显示在顶部的原因,但是出于测试目的,我只是在设置变量.到今天为止,它一直有效(没有做任何更改),而现在运行结果行时,我一直收到此错误:rowXML [[dur]]中的错误:下标超出范围.

I have the following code used to find the travel time between two locations. I am using vba to call the script which is why the command args shows up at the top but for testing purposes I am just setting the variables. This was working until today (didn't change anything) and now I keep getting this error once i run the results line: Error in rowXML[[dur]] : subscript out of bounds.

有人知道这是什么原因吗?

Does anyone have any idea what could be causing this or what it means?

代码:

#install and load necessary packages
#install.packages("gmapsdistance")
#install.packages("devtools")

args<-commandArgs(trailingOnly=T)

library("gmapsdistance")
library("devtools")
devtools::install_github("rodazuero/gmapsdistance")

#input variables from excel
orig <- args[1]
dest <- args[2]
filePath <- args[3]
api_key <- args[4]

 orig <- "London"
 dest <- "Paris"
 filePath <- "C:/Users/gabby/Documents/SeniorYear/SeniorDesign/TravelTimes/Travel_Times.csv"
 api_key <- "############################"

set.api.key(api_key)

#calls google maps and finds the time
results = gmapsdistance(origin = c(orig, dest), destination = c(dest, orig), mode = "driving", traffic_model = "best_guess", 
                        key = api_key, combinations = "pairwise", shape = "wide")

#put results in a data frame
results2 <-  data.frame(results)

#rename the column headings
names(results2) <- c("Origin","Destination", "Time", "X1","X2","Distance","X3","X4","Status")

#delete repeated origin/destination columns
results2$X1 <- NULL
results2$X2 <- NULL
results2$X3 <- NULL
results2$X4 <- NULL

#convert seconds to minutes
results2$Time <- results2$Time/60

#convert meters to miles
results2$Distance <- results2$Distance*0.000621371

#add extra column and input the current date/time for documentation
results2[,"Date"] <- NA
results2[1,"Date"] <- format(Sys.time(), "%a %b %d %X %Y %Z")

#write results2 to a csv file and save it in my folder
write.csv(results2, file = filePath)

推荐答案

我获得了一个API密钥,重现了您的问题,然后逐步浏览了底层函数的源代码.

I obtained an API key, reproduced your problem, and then stepped through the underlying function's source code line by line.

该错误是由以下原因引起的:

The error is caused by the following:

data$Time[i] = as(rowXML[[dur]][1L]$value[1L]$text, 
                        "numeric")

因为对象dur仅包含以下内容:

because the object dur contains only the following:

> dur
[1] "duration"            "duration_in_traffic"

因此,rowXML[[dur]]引发错误.我不确定要指点在哪里,但通常API的更改要比围绕它们构建的软件包快.

Thus rowXML[[dur]] throws the error. I'm not sure where to point the finger, but very often API's change faster than the packages built around them.

尽管如此,您仍然可以像我一样使用源代码来获得结果.只需花费几行代码即可自己清理结果:

Nevertheless, you can still use the source code to get your result, as I did. It just takes a few more lines of code to clean up the results yourself:

xmlChildren(results$row[[1L]])

$status
<status>OK</status> 

$duration
<duration>
  <value>20185</value>
  <text>5 hours 36 mins</text>
</duration> 

$distance
<distance>
  <value>459271</value>
  <text>459 km</text>
</distance> 

$duration_in_traffic
<duration_in_traffic>
  <value>20957</value>
  <text>5 hours 49 mins</text>
</duration_in_traffic> 

attr(,"class")
[1] "XMLInternalNodeList" "XMLNodeList"

根据您在评论中的要求,以下是我为获得此信息所做的更多工作.

Per your request in the comment, here's a bit more about what I did to get this.

首先,从调用此函数的参数中创建参数(例如,将每个参数作为单独的命令运行以创建对象).接下来,加载XMLRcurl库.另外,将您的API密钥放在名为key的对象中.

First, take the arguments from the call to this function and create objects out of them (i.e. just run each argument as an individual command to create the objects). Next, load the XML and Rcurl libraries. Also, put your API key in an object called key.

之后,您只需获取函数的源代码并逐行运行它,就跳过定义函数调用的部分.一路上,您可以创建并设置为""的少量未使用参数.

After that you just take the source code of the function and run it line by line, skipping the part where the function call is defined. Along the way there are a small number of unused arguments which you can just create and set to "".

#    function (origin, destination, combinations = "all", mode, key = #get.api.key(), 
#              shape = "wide", avoid = "", departure = "now", dep_date = "", 
#              dep_time = "", traffic_model = "best_guess", arrival = "", 
#              arr_date = "", arr_time = "") # don't run this

  if (!(mode %in% c("driving", "walking", "bicycling", "transit"))) {
    stop("Mode of transportation not recognized. Mode should be one of ", 
         "'bicycling', 'transit', 'driving', 'walking' ")

  if (!(combinations %in% c("all", "pairwise"))) {
    stop("Combinations between origin and destination not recognized. Combinations should be one of ", 
         "'all', 'pairwise' ")
  }
  if (!(avoid %in% c("", "tolls", "highways", "ferries", "indoor"))) {
    stop("Avoid parameters not recognized. Avoid should be one of ", 
         "'tolls', 'highways', 'ferries', 'indoor' ")
  }
  if (!(traffic_model %in% c("best_guess", "pessimistic", "optimistic"))) {
    stop("Traffic model not recognized. Traffic model should be one of ", 
         "'best_guess', 'pessimistic', 'optimistic'")
  }
  seconds = "now"
  seconds_arrival = ""
  UTCtime = strptime("1970-01-01 00:00:00", "%Y-%m-%d %H:%M:%OS", 
                     tz = "GMT")
  min_secs = round(as.numeric(difftime(as.POSIXlt(Sys.time(), 
                                                  "GMT"), UTCtime, units = "secs")))
  if (dep_date != "" && dep_time != "") {
    depart = strptime(paste(dep_date, dep_time), "%Y-%m-%d %H:%M:%OS", 
                      tz = "GMT")
    seconds = round(as.numeric(difftime(depart, UTCtime, 
                                        units = "secs")))
  }
  if (departure != "now") {
    seconds = departure
  }
  if (departure != "now" && departure < min_secs) {
    stop("The departure time has to be some time in the future!")
  }
  if (dep_date != "" && dep_time == "") {
    stop("You should also specify a departure time in the format HH:MM:SS UTC")
  }
  if (dep_date == "" && dep_time != "") {
    stop("You should also specify a departure date in the format YYYY-MM-DD UTC")
  }
  if (dep_date != "" && dep_time != "" && seconds < min_secs) {
    stop("The departure time has to be some time in the future!")
  }
  if (arr_date != "" && arr_time != "") {
    arriv = strptime(paste(arr_date, arr_time), "%Y-%m-%d %H:%M:%OS", 
                     tz = "GMT")
    seconds_arrival = round(as.numeric(difftime(arriv, UTCtime, 
                                                units = "secs")))
  }
  if (arrival != "") {
    seconds_arrival = arrival
  }
  if (arrival != "" && arrival < min_secs) {
    stop("The arrival time has to be some time in the future!")
  }
  if (arr_date != "" && arr_time == "") {
    stop("You should also specify an arrival time in the format HH:MM:SS UTC")
  }
  if (arr_date == "" && arr_time != "") {
    stop("You should also specify an arrival date in the format YYYY-MM-DD UTC")
  }
  if (arr_date != "" && arr_time != "" && seconds_arrival < 
      min_secs) {
    stop("The arrival time has to be some time in the future!")
  }
  if ((dep_date != "" || dep_time != "" || departure != "now") && 
      (arr_date != "" || arr_time != "" || arrival != "")) {
    stop("Cannot input departure and arrival times. Only one can be used at a time. ")
  }
  if (combinations == "pairwise" && length(origin) != length(destination)) {
    stop("Size of origin and destination vectors must be the same when using the option: combinations == 'pairwise'")
  }
  if (combinations == "all") {
    data = expand.grid(or = origin, de = destination)
  }
  else if (combinations == "pairwise") {
    data = data.frame(or = origin, de = destination)
  }
  n = dim(data)
  n = n[1]
  data$Time = NA
  data$Distance = NA
  data$status = "OK"
  avoidmsg = ""
  if (avoid != "") {
    avoidmsg = paste0("&avoid=", avoid)
  }











  for (i in 1:1:n) {
    url = paste0("maps.googleapis.com/maps/api/distancematrix/xml?origins=", 
                 data$or[i], "&destinations=", data$de[i], "&mode=", 
                 mode, "&sensor=", "false", "&units=metric", "&departure_time=", 
                 seconds, "&traffic_model=", traffic_model, avoidmsg)
    if (!is.null(key)) {
      key = gsub(" ", "", key)
      url = paste0("https://", url, "&key=", key)
    }
    else {
      url = paste0("http://", url)
    }
    webpageXML = xmlParse(getURL(url))
    results = xmlChildren(xmlRoot(webpageXML))
    request.status = as(unlist(results$status[[1]]), "character")
    if (!is.null(results$error_message)) {
      stop(paste(c("Google API returned an error: ", xmlValue(results$error_message)), 
                 sep = ""))
    }
    if (request.status == "REQUEST_DENIED") {
      set.api.key(NULL)
      data$status[i] = "REQUEST_DENIED"
    }
    rowXML = xmlChildren(results$row[[1L]])
    Status = as(rowXML$status[1]$text, "character")
    if (Status == "ZERO_RESULTS") {
      data$status[i] = "ROUTE_NOT_FOUND"
    }
    if (Status == "NOT_FOUND") {
      data$status[i] = "PLACE_NOT_FOUND"
    }
    if (Status == "OVER_QUERY_LIMIT") {
      stop("You have exceeded your allocation of API requests for today.")
    }
    if (data$status[i] == "OK") {
      data$Distance[i] = as(rowXML$distance[1]$value[1]$text, 
                            "numeric")
      dur = grep("duration", names(rowXML), value = TRUE)
      data$Time[i] = as(rowXML[[dur]][1L]$value[1L]$text, 
                        "numeric")
    }
  }


  datadist = data[c("or", "de", "Distance")]
  datatime = data[c("or", "de", "Time")]
  datastat = data[c("or", "de", "status")]
  if (n > 1) {
    if (shape == "wide" && combinations == "all") {
      Distance = reshape(datadist, timevar = "de", idvar = c("or"), 
                         direction = "wide")
      Time = reshape(datatime, timevar = "de", idvar = c("or"), 
                     direction = "wide")
      Stat = reshape(datastat, timevar = "de", idvar = c("or"), 
                     direction = "wide")
    }
    else {
      Distance = datadist
      Time = datatime
      Stat = datastat
    }
  }
  else {
    Distance = data$Distance[i]
    Time = data$Time[i]
    Stat = data$status[i]
  }
  output = list(Time = Time, Distance = Distance, Status = Stat)

这篇关于R代码gmapsdistance的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆