如何利用 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:具體信息,包括geocoding

Amap_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 lat

1 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和嵌入式有哪些區別於聯繫?
對做黑客感興趣該從什麼起步,怎樣發展?
注釋會影響解釋型語言的效率嗎?

TAG:編程語言 | R編程語言 |