R 代码迭代谷歌地图距离查询的数据帧行

标签 r loops dataframe google-distancematrix-api

我正在寻找一些帮助来编写一些 R 代码以遍历数据框中的行并将每行中的值传递给函数并将输出打印到 excel 文件、txt 文件或仅在控制台中。

这样做的目的是使用此网站上的功能自动执行一系列距离/时间查询(数百个)到谷歌地图:http://www.nfactorialanalytics.com/r-vignette-for-the-week-finding-time-distance-between-two-places/

该网站的功能如下:

library(XML)
library(RCurl)
distance2Points <- function(origin,destination){
 results <- list();
 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)
 time <- xmlValue(xmlChildren(xpathApply(xmlfile,"//duration")[[1]])$value)
 distance <- as.numeric(sub(" km","",dist))
 time <- as.numeric(time)/60
 distance <- distance/1000
 results[['time']] <- time
 results[['dist']] <- distance
 return(results)
}

dataframe 将包含两列:原始邮政编码和目的地邮政编码(加拿大,嗯?)。我是初学者 R 程序员,所以我知道如何使用 read.table 将 txt 文件加载到数据框中。我只是不确定如何遍历数据帧,每次将值传递给 distance2Points 函数并执行。我认为这可以使用 for 循环或应用调用之一来完成?

感谢您的帮助!

编辑:

为简单起见,假设我想将这两个向量转换为数据帧

> a <- c("L5B4P2","L5B4P2")
> b <- c("M5E1E5", "A2N1T3")
> postcodetest <- data.frame(a,b)
> postcodetest
       a      b
1 L5B4P2 M5E1E5
2 L5B4P2 A2N1T3

我应该如何迭代这两行以从 distance2Points 函数返回距离和时间?

最佳答案

这是一种方法,使用 lapply 生成一个列表,其中包含数据中每一行的结果,并使用 Reduce(rbind, [yourlist]) 来将该列表连接到一个数据框中,其行对应于原始列表中的行。为了实现这一点,我们还必须调整原始函数中的代码以返回单行数据框,所以我在这里完成了。

distance2Points <- function(origin,destination){

  require(XML)
  require(RCurl)

  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)
  time <- xmlValue(xmlChildren(xpathApply(xmlfile,"//duration")[[1]])$value)
  distance <- as.numeric(sub(" km","",dist))
  time <- as.numeric(time)/60
  distance <- distance/1000
  # this gives you a one-row data frame instead of a list, b/c it's easy to rbind
  results <- data.frame(time = time, distance = distance)
  return(results)
}

# now apply that function rowwise to your data, using lapply, and roll the results
# into a single data frame using Reduce(rbind)
results <- Reduce(rbind, lapply(seq(nrow(postcodetest)), function(i)
  distance2Points(postcodetest$a[i], postcodetest$b[i])))

应用于示例数据的结果:

> results
        time distance
1   27.06667   27.062
2 1797.80000 2369.311

如果您希望在不创建新对象的情况下执行此操作,您还可以编写单独的函数来计算时间和距离——或者将这些输出作为选项的单个函数——然后使用sapply 或只是 mutate 以在原始数据框中创建新列。下面是使用 sapply 时的样子:

distance2Points <- function(origin, destination, output){

  require(XML)
  require(RCurl)

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

  xmlfile <- xmlParse(getURL(xml.url))

  if(output == "distance") {

    y <- xmlValue(xmlChildren(xpathApply(xmlfile,"//distance")[[1]])$value)
    y <- as.numeric(sub(" km", "", y))/1000

  } else if(output == "time") {

    y <- xmlValue(xmlChildren(xpathApply(xmlfile,"//duration")[[1]])$value)
    y <- as.numeric(y)/60

  } else {

    y <- NA    

  }

  return(y)

}

postcodetest$distance <- sapply(seq(nrow(postcodetest)), function(i)
  distance2Points(postcodetest$a[i], postcodetest$b[i], "distance"))

postcodetest$time <- sapply(seq(nrow(postcodetest)), function(i)
  distance2Points(postcodetest$a[i], postcodetest$b[i], "time"))

下面是如何使用 mutatedplyr 管道中执行此操作:

library(dplyr)

postcodetest <- postcodetest %>%
  mutate(distance = sapply(seq(nrow(postcodetest)), function(i)
           distance2Points(a[i], b[i], "distance")),
         time = sapply(seq(nrow(postcodetest)), function(i)
           distance2Points(a[i], b[i], "time")))

关于R 代码迭代谷歌地图距离查询的数据帧行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40406825/

相关文章:

r - 将数据框字符串列转换/转置为单行

r - [R] 中加载和附加的区别

r - spplot图例在 map 中的自定义位置

Python嵌套循环和更新集

python - 遍历一个 numpy 数组,然后索引另一个数组中的值

r - 如何抑制代码但在 R markdown 中显示图?

使用元素类型和 id 通配符的 .each 循环的 JavaScript 版本

python - 映射和合并来自另一个数据框的值

python - 在 python 中使用 zip 函数迭代几列,给出错误

python - 查询字符串值的数据框列