如何利用 R 語言來獲得某個具體地址的經緯度?
有木有前輩指導一下,是否有可以利用R語言包,輸入地址名稱來返回該地址的經緯度。
這種轉換一般都需要一個服務,去搜索Geocoding就明白了。
R裡頭的ggmap包有個函數封裝了google的這個服務。如果需要國內的服務,可以自己找百度的API文檔,用R的Rcurl+json去解析。@t.s.helianthus已經寫得很詳細了,我補充一個更加簡單的辦法,其實就是李艦寫的RbaiduLBS包:
library(RbaiduLBS)
getGeocoding(address = "海淀區海淀大街3號", city = "北京", ak = "你的百度地圖ak密鑰")
address city lat lng precise confidence level
1 海淀區海淀大街3號 北京 39.98975 116.3205 1 80 道路
#2.0版已經更新
簡單粗暴的甩上代碼。其實就是肖凱老師說的RCurl+rjson包。
百度地圖Geocoding-API :webapi/direction-api
下面的AK密鑰必須替換成自己申請的。#####自定義部分-beign#####
#file
filename &<- "filename"
#輸入自己申請的百度地圖的AK密鑰 ##下面的密鑰是假的,別信
keylist.XXX &<- c(
"14utEK6S3Y5GEM6QN",
"C6Zfr1F3mgVHPGDOb",
"gnC9ldiox7nUweT4C",
"7MmwUq9lR7BsAPrkE",
"Qz8ryKGGQfMEmqZPg",
"KqKGv2HrjHGcaLu5o"
)
keylist.YYY&<- c(
"x66ZNVGeV8SGRs1CW",
"tKkiZzgYBuRkKw7Hc",
"GYgUqu5ddcDI3eWM2",
"qPlXFV5i72BuXhwFy",
"VNzdUpswmBCKjpRKM",
"4RHqLGD5ZNrCMHuOw"
)
# 載入需要的文件
add &<- read.csv("add.csv")
# 地址轉換列表
add.orignal &<- add$query
# 城市名稱設定
# city &<- paste(add$city,"市",sep="")
city &<- c()
keylist &<- keylist.XXX #請換成自己的密鑰列表
keylist2 &<- keylist.YYY #請換成自己的密鑰列表
#####自定義部分-end#####
#####自動運行-begin#####
# 瀏覽器報頭
myheader=c(
"User-Agent"="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:46.0) Gecko/20100101 Firefox/46.0",
"Accept"="text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language"="zh-TW,en-US;q=0.7,en;q=0.3",
"Connection"="keep-alive",
"X-Requested-With"="XMLHttpRequest",
"Accept-Charset"="GB2312,utf-8;q=0.7,*;q=0.7"
)
#載入需要的包
library(rjson)
library(RCurl)
library(httr)
#設定空向量
baidu.lat &<- c()
baidu.lng &<- c()
baidu.address &<-c()
baidu.geo &<- c()
baidu.url &<- c()
location &<- enc2native(as.character(add.orignal))
#列表循環-begin#
total &<- length(add.orignal)
pb &<- txtProgressBar(0,total,style = 3)
for (i in 1:total) {
if(i&>=0 i &<2000){key &<- keylist[1]}
if(i&>=2000 i &<4000){key &<- keylist[2]}
if(i&>=4000 i &<6000){key &<- keylist[3]}
if(i&>=6000 i &<8000){key &<- keylist[4]}
if(i&>=8000 i &<10000){key &<- keylist[5]}
if(i&>=10000 i &<12000){key &<- keylist2[1]}
if(i&>=12000 i &<14000){key &<- keylist2[2]}
if(i&>=14000 i &<16000){key &<- keylist2[3]}
if(i&>=16000 i &<18000){key &<- keylist2[4]}
if(i&>=18000 i &<20000){key &<- keylist2[5]}
#建立地址轉換網址
location &<- as.character(add.orignal[i])
#city.location &<- city[i]
url &<- URLencode(paste("http://api.map.baidu.com/geocoder/v2/?ak=",key,"output=jsonaddress=",location,"city=",city,sep = ""))
# 捕獲連接對象
msg.load &<- tryCatch({
connect &<- getURL(url,httpheader=myheader)
msg.load &<- "TRUE"
}, error = function(e) {
"error"
}
)
#錯誤信息記錄
if(msg.load=="error"){
Sys.sleep(runif(1,3,10))
msg.load &<- tryCatch({
connect &<- content(GET(url,add_headers(myheader)))
msg.load &<- "TRUE"
}, error = function(e) {
"error"
}
)
}
#錯誤信息記錄
if(msg.load=="error"){
Sys.sleep(runif(1,3,10))
msg.load &<- tryCatch({
connect &<- readLines(url,encoding = "utf-8")
msg.load &<- "TRUE"
}, error = function(e) {
"error"
}
)
}
baidu.geo &<- fromJSON(connect)
#錯誤信息記錄
if(msg.load=="error"){
#載入出錯
temp.lat&<-"error1"
temp.lng&<-"error1"
}else{
# 處理json對象
temp.lat&<-temp.geo$result$location$lat
temp.lng&<-temp.geo$result$location$lng
if(length(temp.lat) == 0) {
#獲取出錯
baidu.geo &<- "error2"
temp.lat &<- "error2"
temp.lng &<- "error2"
}
}
temp.location &<- location
baidu.geo &<-c(baidu.geo,temp.geo)
baidu.lat &<- c(baidu.lat,temp.lat)
baidu.lng &<- c(baidu.lng,temp.lng)
baidu.url &<- c(baidu.url,url)
baidu.address &<- c(baidu.address,temp.location)
setTxtProgressBar(pb,i)
save.image("Baidu-geocoding.RData")
}
#列表循環-end#
content &<- data.frame(
baidu.lat,
baidu.lng,
baidu.address,
baidu.url)
#####自動運行-end#####
#查看數據
content
#導出數據
write.csv(content,file=paste(filename,"-",Sys.Date(),"baidu-geo.csv",sep=""))
代碼中使用了3種網頁獲取方式,以避免中間出現無法獲取的經緯度地址會停止運行(加了trycatch )
高德地圖Geocoding-API Web服務 API | 高德開放平台
高德的話,只是地址和json獲取的規則有小變動。大體一樣。另外寫了一個函數,可以封裝了2種可能需要的類型,更適合調用。
tip:地址輸入提示info:具體信息,包括geocodingAmap_geo &<- function(add,type,key){
add &<- as.character(add);type=as.character(type)
amap = url = NULL
if(type == "tip"){url &<- paste("http://restapi.amap.com/v3/assistant/inputtips?key=",key,"keywords=",URLencode(enc2utf8(add)),"types=city=datatype=all",sep="")}
if(type == "info"){url &<- paste("http://restapi.amap.com/v3/place/text?key=",key,"keywords=",URLencode(enc2utf8(add)),"types=city=children=1offset=20page=1extensions=base",sep="")}
msg.load &<- tryCatch({
connect &<- getURL(url,httpheader=myheader,.encoding="utf-8")
amap &<- fromJSON(connect)
msg.load &<- "TRUE"
}, error = function(e) {
"error"
}
)
if(msg.load=="error"){
Sys.sleep(runif(1,2,5))
msg.load &<- tryCatch({
amap &<- content(GET(url,add_headers(myheader)))
msg.load &<- "TRUE"
}, error = function(e) {
"error"
}
)
}
return(amap)
}
@examples key &<- "489692aa00caa8f4ec60"; add.orignal &<- "上海市虹橋火車站";qurey.type &<- "info";amap &<- addAmap(add=add.orignal,type=qurey.type,key=key)
網址是否需要編碼好像評論區不統一,那麼就各自取用吧。
另外有評論反應網址編碼轉換出錯的問題。中文需要經過正確編碼轉換後再使用URLencode(),中文編碼轉換參考enc2utf8()、enc2native(),看需求判斷。百度和高德的地理編碼標準不太一樣不能混用。【據說國內使用的google/bing用的地理編碼都是高德的,也就是火星坐標;百度的是火星坐標二次轉換之後的坐標系。】
數據結構,其實就是地址……如果有已知城市最好帶上(哦,高德我忘加了……)ggmap包geocode()比如:&> geocode("Beijing") lon lat1 116.4075 39.90403
可以買個api
library(REmap)
city_vec = c("北京","Shanghai","廣州")
get_city_coord("Shanghai")
get_geo_position (city_vec)
簡潔方便
如果是反向解析怎麼寫代碼?
樓主,那個address寫錯了,應該是baidu_address,不然前面定義空向量的時候就應該建成address
推薦閱讀:
※為什麼不能亂點技能樹?
※有 Memory Segmentation 和 Paging 等技術時,C/C++,Pascal 等低級語言中對內存布局的控制意義何在?
※FPGA和嵌入式有哪些區別於聯繫?
※對做黑客感興趣該從什麼起步,怎樣發展?
※注釋會影響解釋型語言的效率嗎?