You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google Maps API返回ZERO_RESULTS时如何生成含NA的DataFrame?

解决ggmap mapdist transit模式下ZERO_RESULTS导致的报错问题

问题说明

使用ggmap的mapdist函数计算公共交通(transit模式)的距离与时间时,若部分地址对无可用公共交通连接,Google API会返回ZERO_RESULTS状态,此时mapdist的simple输出会跳过该条目,导致结果DataFrame的行数与输入地址对数不匹配,触发bind_cols()的尺寸不匹配报错:

Error in bind_cols(): Can't recycle ..1 (size 16) to match ..2 (size 14).

需要修改代码,让无结果的地址对在最终DataFrame中填充NA值,而非报错。

原始代码

ggmap::register_google("your_key", write=TRUE) 

gmap.trans <- data.frame(
  gmap.address = c("13187 berlin, germany", "14052 berlin, germany", "10315 berlin, germany", "10249 berlin, germany", "18609 binz, germany", "10369 berlin, germany", "15370 petershagen/eggersdorf, germany", "15806 trebbin, germany", "10719 berlin, germany", "17192, germany", "19053 schwerin, germany", "10717 berlin, germany", "10439 berlin, germany", "12489 berlin, germany", "12527 berlin, germany", "12621 berlin, germany"),
  dest = c("Oetztal Bahnhof , Österreich"))

PubTrans <- mapdist(from = gmap.trans$gmap.address,
                   to = gmap.trans$dest,
                   mode = "transit",
                   output = "simple")

解决方案一:用tryCatch逐个处理地址对

通过逐个处理每个地址对,捕获ZERO_RESULTS触发的错误,返回填充NA的行,最后合并成完整DataFrame:

library(ggmap)
library(dplyr)
library(purrr)

ggmap::register_google("your_key", write=TRUE) 

gmap.trans <- data.frame(
  gmap.address = c("13187 berlin, germany", "14052 berlin, germany", "10315 berlin, germany", "10249 berlin, germany", "18609 binz, germany", "10369 berlin, germany", "15370 petershagen/eggersdorf, germany", "15806 trebbin, germany", "10719 berlin, germany", "17192, germany", "19053 schwerin, germany", "10717 berlin, germany", "10439 berlin, germany", "12489 berlin, germany", "12527 berlin, germany", "12621 berlin, germany"),
  dest = rep("Oetztal Bahnhof , Österreich", 16)
)

# 定义单个地址对的处理函数
get_transit_info <- function(from_addr, to_addr) {
  tryCatch(
    mapdist(from = from_addr, to = to_addr, mode = "transit", output = "simple"),
    error = function(e) {
      # 无结果时返回填充NA的行
      data.frame(
        from = from_addr,
        to = to_addr,
        m = NA_real_,
        km = NA_real_,
        miles = NA_real_,
        seconds = NA_real_,
        minutes = NA_real_,
        hours = NA_real_,
        mode = "transit",
        stringsAsFactors = FALSE
      )
    }
  )
}

# 遍历所有地址对并合并结果
PubTrans <- map2_dfr(gmap.trans$gmap.address, gmap.trans$dest, get_transit_info)

解决方案二:直接调用Google Distance Matrix API

绕过mapdist函数,直接调用API接口解析原始返回结果,更灵活地处理ZERO_RESULTS状态:

library(httr)
library(jsonlite)
library(dplyr)

api_key <- "your_key"
base_url <- "https://maps.googleapis.com/maps/api/distancematrix/json"

gmap.trans <- data.frame(
  gmap.address = c("13187 berlin, germany", "14052 berlin, germany", "10315 berlin, germany", "10249 berlin, germany", "18609 binz, germany", "10369 berlin, germany", "15370 petershagen/eggersdorf, germany", "15806 trebbin, germany", "10719 berlin, germany", "17192, germany", "19053 schwerin, germany", "10717 berlin, germany", "10439 berlin, germany", "12489 berlin, germany", "12527 berlin, germany", "12621 berlin, germany"),
  dest = rep("Oetztal Bahnhof , Österreich", 16)
)

# 发送API请求
response <- GET(base_url, query = list(
  origins = paste(gmap.trans$gmap.address, collapse = "|"),
  destinations = gmap.trans$dest[1],
  mode = "transit",
  key = api_key
))
content <- fromJSON(content(response, "text"))

# 解析结果并构建DataFrame
PubTrans <- tibble(
  from = content$origin_addresses,
  to = rep(content$destination_addresses[1], length(content$origin_addresses)),
  status = sapply(content$rows$elements, function(x) x$status),
  m = sapply(content$rows$elements, function(x) ifelse(x$status == "OK", x$distance$value, NA)),
  km = sapply(content$rows$elements, function(x) ifelse(x$status == "OK", x$distance$value / 1000, NA)),
  miles = sapply(content$rows$elements, function(x) ifelse(x$status == "OK", x$distance$value / 1609.34, NA)),
  seconds = sapply(content$rows$elements, function(x) ifelse(x$status == "OK", x$duration$value, NA)),
  minutes = sapply(content$rows$elements, function(x) ifelse(x$status == "OK", x$duration$value / 60, NA)),
  hours = sapply(content$rows$elements, function(x) ifelse(x$status == "OK", x$duration$value / 3600, NA)),
  mode = "transit"
)

说明

  • 方案一基于原mapdist函数改造,代码改动较小,适合习惯使用ggmap的用户
  • 方案二直接调用API,能完整获取所有返回状态,更可控,适合需要自定义处理逻辑的场景

内容的提问来源于stack exchange,提问作者Pia Berer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 09:17:33