gpt4 book ai didi

r - 使用打开的 mapquestapi 在 R 中对批处理地址进行地理编码

转载 作者:行者123 更新时间:2023-12-04 01:59:05 25 4
gpt4 key购买 nike

目标:使用R,通过open.mapquestapi获取地址向量的经纬度数据

出发点:geocode来自 ggmap包被限制为每天 2500 次查询,我需要找到一种不同的方式(我的 data.frame 包含 9M 条目)。数据科学工具包不是一种选择,因为我的大部分地址都位于英国/美国以外。我在 http://rpubs.com/jvoorheis/Micro_Group_Rpres 上发现了这个很棒的片段使用 open.mapquestapi。

geocode_attempt <- function(address) {
URL2 = paste("http://open.mapquestapi.com/geocoding/v1/address?key=", "Fmjtd%7Cluub2huanl%2C20%3Do5-9uzwdz",
"&location=", address, "&outFormat='json'", "boundingBox=24,-85,50,-125",
sep = "")
# print(URL2)
URL2 <- gsub(" ", "+", URL2)
x = getURL(URL2)
x1 <- fromJSON(x)
if (length(x1$results[[1]]$locations) == 0) {
return(NA)
} else {
return(c(x1$results[[1]]$locations[[1]]$displayLatLng$lat, x1$results[[1]]$locations[[1]]$displayLatLng$lng))
}
}
geocode_attempt("1241 Kincaid St, Eugene,OR")

我们需要这些库:
library(RCurl)
library(rjson)
library(dplyr)

让我们创建一个包含 5 个地址的模型 data.frame。
id <- c(seq(1:5))
street <- c("Alexanderplatz 10", "Friedrichstr 102", "Hauptstr 42", "Bruesseler Platz 2", "Aachener Str 324")
postcode <- c("10178","10117", "31737", "50672", "50931")
city <- c(rep("Berlin", 2), "Rinteln", rep("Koeln",2))
country <- c(rep("DE", 5))

df <- data.frame(id, street, postcode, city, country

添加纬度 lat和经度 lon data.frame 的变量,我们可以使用 for -环形。我将提供代码,只是为了证明该函数在原理上是有效的。
for(i in 1:5){
df$lat[i] <- geocode_attempt(paste(df$street[i], df$postcode[i], df$city[i], df$country[i], sep=","))[1]
df$lon[i] <- geocode_attempt(paste(df$street[i], df$postcode[i], df$city[i], df$country[i], sep=","))[2]
}

从性能的角度来看,这段代码非常糟糕。即使对于这个小的 data.frame,我的计算机也花了大约 9 秒,很可能是由于网络服务查询,但没关系。所以我可以在我的 9M 行上运行这段代码,但时间会很长。

我的尝试是利用 mutate来自 dplyr 的函数包裹。
这是我尝试过的:
df %>%
mutate(lat = geocode_attempt(paste(street, postcode, city, country, sep=","))[1],
lon = geocode_attempt(paste(street, postcode, city, country, sep=","))[2])
system.time仅在 2.3 秒内停止。还不错。但问题是:
 id             street postcode    city country      lat      lon
1 1 Alexanderplatz 10 10178 Berlin DE 52.52194 13.41348
2 2 Friedrichstr 102 10117 Berlin DE 52.52194 13.41348
3 3 Hauptstr 42 31737 Rinteln DE 52.52194 13.41348
4 4 Bruesseler Platz 2 50672 Koeln DE 52.52194 13.41348
5 5 Aachener Str 324 50931 Koeln DE 52.52194 13.41348
latlon所有条目完全相同。据我了解, mutate函数正在按行工作。但在这里, lat 和 lon 是从第一行计算出来的。因此,第一行是正确的。有谁知道为什么?我提供的代码是完整的。没有额外加载。有任何想法吗?如果您有一种高性能的替代方法而不是优化我的代码,我也将不胜感激。

最佳答案

您可能需要矢量化您的 geocode_attempt按列执行的功能:

vecGeoCode<-Vectorize(geocode_attempt,vectorize.args = c('address'))

然后调用:
df %>%
mutate(lat = vecGeoCode(paste(street, postcode, city, country, sep=","))[1,],
lon =vecGeoCode(paste(street, postcode, city, country, sep=","))[2,])

为了加快速度,您可能需要查看 API 的批处理模式,以一次性获得多达 100 个经纬度。

要使用 API 的批处理请求,您可以使用此函数:
geocodeBatch_attempt <- function(address) {
#URL for batch requests
URL=paste("http://open.mapquestapi.com/geocoding/v1/batch?key=", "Fmjtd%7Cluub2huanl%2C20%3Do5-9uzwdz",
"&location=", paste(address,collapse="&location="),sep = "")

URL <- gsub(" ", "+", URL)
data<-getURL(URL)
data <- fromJSON(data)

p<-sapply(data$results,function(x){
if(length(x$locations)==0){
c(NA,NA)
} else{
c(x$locations[[1]]$displayLatLng$lat, x$locations[[1]]$displayLatLng$lng)
}})
return(t(p))
}

要测试它:
#make a bigger df from the data (repeat the 5 lines 25 times)
biggerDf<-df[rep(row.names(df), 25), ]

#add a reqId column to split the data in batches of 100 requests
biggerDf$reqId<-seq_along(biggerDf$id)%/%100

#run the function, first grouping by reqId to send batches of 100 requests
biggerDf %>%
group_by(reqId) %>%
mutate(lat = geocodeBatch_attempt(paste(street, postcode, city, country, sep=","))[,1],
lon =geocodeBatch_attempt(paste(street, postcode, city, country, sep=","))[,2])

关于r - 使用打开的 mapquestapi 在 R 中对批处理地址进行地理编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28680992/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com