在R中从Census地理编码API提取经纬度及处理空值
解决方案
问题根源
- 当地址无匹配结果时,
addressMatches是空列表,原代码直接提取coordinates会返回NULL而非预期的NA - 有匹配结果时,
addressMatches是列表结构,原代码未通过索引([[1]])访问第一个匹配项,导致提取失败 - 原函数未保留输入地址,无法直接生成包含地址列的目标数据框
修改后的完整代码
library(httr) library(jsonlite) fetch_geocodes <- function(address) { base_url <- "https://geocoding.geo.census.gov/geocoder/geographies/onelineaddress" params <- list( address = address, benchmark = "Public_AR_Current", vintage = "Current_Current", format = "json" ) # 添加延迟避免触发API请求限制 Sys.sleep(0.5) response <- GET(url = base_url, query = params) if (status_code(response) == 200) { data <- content(response, "parsed") # 初始化经纬度默认值为NA lon <- NA_real_ lat <- NA_real_ # 检查是否有匹配结果 if (length(data$result$addressMatches) > 0) { # 取第一个匹配结果(API按相关性排序) first_match <- data$result$addressMatches[[1]] lon <- first_match$coordinates$x lat <- first_match$coordinates$y } # 返回包含原地址、经纬度的列表 return(list( full_address = address, longitude = lon, latitude = lat )) } else { # 请求失败时返回警告并保留原地址+NA,避免中断批量处理 warning(paste("地址", address, "请求失败,状态码:", status_code(response))) return(list( full_address = address, longitude = NA_real_, latitude = NA_real_ )) } } # 测试地址列表 addresses <- c("Riverside Dr, Apple Valley, CA, 92307", "11 Wall Street, New York, NY 10005") # 批量获取结果并转换为数据框 geocode_results <- lapply(addresses, fetch_geocodes) final_df <- do.call(rbind.data.frame, geocode_results) # 查看最终结果 print(final_df)
关键改动说明
- 空匹配处理:通过
length(data$result$addressMatches) > 0判断是否有匹配结果,无匹配时保留NA值 - 列表索引访问:用
[[1]]获取第一个匹配项,符合API返回的相关性排序逻辑 - 保留原地址:函数返回包含原地址的列表,直接转换为数据框即可得到目标结构
- 错误容错:请求失败时返回警告而非终止,保证批量处理不会中断
- 请求延迟:添加
Sys.sleep(0.5)避免短时间内发送过多请求触发API限制(美国普查局API建议请求间隔≥0.5秒)
输出结果
full_address longitude latitude 1 Riverside Dr, Apple Valley, CA, 92307 NA NA 2 11 Wall Street, New York, NY 10005 -74.01073 40.70714
内容的提问来源于stack exchange,提问作者Fox_Summer
相关产品推荐
相关产品推荐

