&color(black,#CCFFCC){LINK:[[[GoogleEarthとR]]][[[ShapeFileライブラリ]]][[[kmlラボ]]][[[空間的なデータの分析]]][[[Rでジオコーディング]]][[[RでGPS]]]};~
----
目次

#contents
----
&color(black){論文引用・書籍等に引用する場合の著作権についての連絡>>[[okinawa]]};~
----
*目的 [#zcea8c20]
GoogleMapやGoogleEarthのおかげで、最近ジオコーディングという言葉がインターネットで頻繁に使われだしている。~
ジオコーディングとは簡単に言えば、住所や郵便番号情報から、緯度・経度の位置情報に変換する技術のことであるが、WebAPIを利用したものや完全にフリーで配布されているもの、有償でかなりお高いものなど多々存在する。~
最近になって勢力を拡大してきているのが、WebAPIを利用したジオコーダー(ジオコーディング用のプログラム)で、もっとも有名なのがGoogleMapAPIに含まれているジオコーダーである。~
また、国から「街区レベル位置参照情報ダウンロードサービス」が開始されたり、郵便番号データがダウンロードできるようになってからは、これらのデータを組み合わせてジオコーディングを行うものが出てきている。~
~
ここでは、ジオコーディングの情報を収集するとともに、Rを用いたジオコーディングについて検証していくこととする。~
基本的には、Rのみでジオコーディングを可能にすることが目標である。~
GoogleEarthのジオコーディングはすばらしいが、なにしろ変換スピードが遅いのがネックである。(ちなみにGoogleMapAPIの日本版ジオコーディング部分はゼンリンのものが使われていると言われている。)~

(注意)~
ジオコーディングを業務用に利用するならば、ジオコーディングする前に「住所情報の正規化」という作業が必要になることが多い。~
つまり、業務で入力されている住所がきちんとした住所になっていない(たとえば、**市を端折って市内と書いてあったりする)ので、まずきちんとした住所になるように文字列を整える必要がある。~
そういう意味では、文書としての住所を解析して正規化する文書解析という分野の知識も必要になる。~

*利用するパッケージ [#fe3ac694]
RCurl~
XML~
rjson~
SSOAP~

*ツールとデータ [#ac0bfd88]

&color(black){ジオコーディングツール};~
無償版:~
[GoogleMapAPI] http://www.google.com/apis/maps/documentation/~
[CSVアドレスマッチングサービス] http://www.tkl.iis.u-tokyo.ac.jp/~sagara/geocode/overview.html~
[gコンテンツ流通推進協議会] http://www.g-contents.jp/~
[geocoder.ja] http://www.postlbs.org/~
[JNS住所認識システム]http://nlftp.mlit.go.jp/isj/jns_agreement.html~

有償版:~
[jasminesoft住所正規化コンバータ] http://anorm.jp/~
[アルプス社] http://www.alpsmap.jp/mapinfo/data/geocoding/

&color(black){ジオコーディング用データ};~
[街区レベル位置参照情報ダウンロードサービス] http://nlftp.mlit.go.jp/isj/~
[郵便番号ダウンロード] http://www.post.japanpost.jp/zipcode/download.html~

&color(black){文字列検索アルゴリズム};~
[1]http://fujimiya.net/?Boyer-Moore%20Fast%20String%20Searching%20Algorithm~
[2]http://d.hatena.ne.jp/siokoshou/20060325~
[3]http://www.dbsj.org/Japanese/DBSJLetters/vol1/no1/ronbun/Sagara.pdf~

&color(black){日本語形態素解析};~
[1]YahooJapan:http://developer.yahoo.co.jp/jlp/MAService/V1/parse.html

*RCODE [#r5f26321]
**1.街区レベル位置参照情報データを利用した簡易ジオコーディング[#wbee21fa]
事前に街区レベル位置参照情報ダウンロードサービスから対象となるデータをダウンロードして解凍してください。~
下記の例は、沖縄県全域データを利用したものです。~

 x<- read.csv("c:\\47_2006.csv")
 y<- paste(x$都道府県名,x$市区町村名,x$大字.町丁目,x$街区符号.地番,sep="")
 target<- "沖縄県島尻郡八重瀬町後原566"
 xnum<-pmatch(target,y)
 z<-x[xnum,8:9]
 print(z)
  > print(z)
           緯度     経度
 95660 26.14762 127.7343


(注)まったく役に立ちませんが、とりあえず住所完全一致でのジオコーディング。一度変数に入れてしまえば、3行目以降のみで可能。さて、住所の正規化をどうするか・・・。

 options(digits=10)
 target<- "浦添市当山二丁目"
 xnum<-grep(target,y)
 z<-x[xnum,1:9]
 mean(z[8:9])
 > mean(z[8:9])
       緯度        経度 
 26.2515489 127.7348568 

(注)grepだと結構いい感じであいまい検索してくれる。

**2.[[GoogleEarthとR]]のコメント欄にXMLパッケージとGoogleEarthを利用したコードが岡田先生により掲載されています。[#b484cc6a]
***1)GoogleEarthを利用したジオコーディング: [#q61bf0aa]
 # hospdは $Addrに住所, $Nameに名前が入っているデータフレーム。
 library(XML)
 makePlacemark <- function(x) {
   addr=xmlNode("address", xmlTextNode(hospd$Addr[x]));
   name=xmlNode("name", xmlTextNode(hospd$Name[x]));
   return(xmlNode("Placemark",addr,name));
 }
 addrList <- lapply(1:nrow(hospd), makePlacemark)
 d<-xmlNode("Document")
 for(i in 1:length(addrList)) { d$children[[i]] <- addrList[[i]] }
 p <- xmlNode("kml", d)
 sink(file("hospd.kml",encoding="utf-8",open="w")) #なかまさんのものをくっつけました
 print(p)
 sink()
出力されたhospd.kmlをGoogleEarthに読み込むと、GEが自動的にジオコーディングして表示してくれます。(遅いです)想像ですが、GoogkeMapAPIのジオコーディングを使っていると思いますので、ゼンリンのデータを用いた独自解析のものでしょう。~

***2)GE上で「情報を取得」などを行ってから再びKMLに書き出すと、coordinatesエレメントがついたKMLになりますが、それを再度Rにとりこむ関数: [#rd67160c]

 placemark2GeoData <- function(rootNode) {
	findDoc <- function(x) {
		if(xmlName(x) == "Document") {
			return(x)
		}
		for(m in xmlChildren(x)) {
			n <- findDoc(m)
			if(!is.null(n)) {
				return(n)
			}
		}
		return(NULL)
	}
	ininode <- findDoc(rootNode)
	namev <- vector()
	addrv <- vector()
	longv <- vector()
	lattv <- vector()
	for(node in xmlChildren(ininode)) {
		if(xmlName(node) == "Placemark") { 
			n <- NULL
			a <- NULL
			gd <- NULL
			for(i in xmlChildren(node)) {
				if(xmlName(i) == "name") {
					n <- xmlValue(i$children[[1]])
				} else if(xmlName(i) == "address") {
					a <- xmlValue(i$children[[1]])
				} else if(xmlName(i) == "Point") {
					gd <-   strsplit(xmlValue(i$children[[1]]$children[[1]]),",")[[1]]
				} 
			}
			if(!(is.null(gd) | is.null(a) | is.null(n)) ) {
				namev <- append(namev, n)
				addrv <- append(addrv, a)
				longv <- append(longv, gd[1])
				lattv <- append(lattv, gd[2])
			}
		}
	}
	return(data.frame(Name=namev, Address=addrv, Longitude=longv,  Lattitude=lattv))
 }

こんな風に使います

 doc <- xmlTreeParse("ih.kml")
 hospg <- placemark2GeoData(xmlRoot(doc)) # これでLong, Latが入ったデータフレームができる
 merge(hospg,hospd,by="Name")

**3.GoogleMapAPIのGeoCording(HTTP Request)を利用してジオコーディング [#y167e962]
 ##GoogleMapAPIを用いたジオコーディング
 address<-"沖縄県那覇市久米2丁目4番14号"
 returnform<-"xml"#xmlorjson
 key<-"ABQIAAAA7Qa-RE_JYtVliR9OTauOexScAlgT1OMB91Iojh4cvnPDirRWVBRkKoWJQNoMN19LbzuRx7z0aIWHTQ"#ここはGoogleAPIでもらったkeyを登録
 text1<-"http://maps.google.com/maps/geo?q="
 text2<-"&output="
 text3<-"&key="
 savefile<-"c:\\geocode.xml"
 EncodeAddress<-paste(c("",charToRaw(iconv(address,"CP932","UTF-8"))),collapse="%")#なかまさんのURLエンコード
 URLText<-paste(text1,EncodeAddress,text2,returnform,text3,key,sep="")
 download.file(URLText,savefile)

で、c:直下にgeocode.xmlで落ちてきます。returnform<-"xml"#xmlorjsonのところで、返り値のフォームを指定してます。(XML形式かJSON形式か)xmlのデコードは次の機会に・・・。

**4.YahooMapAPIを利用してジオコーディング [#ed95ba3b]
 ##YahooMapAPIを用いたジオコーディング
 address<-"沖縄県那覇市久米2丁目4番14号"
 #returnform<-"xml"#xmlorjson
 appid<-"YahooDemo"
 text1<-"http://api.map.yahoo.co.jp/LocalSearchService/V1/LocalSearch?"
 text2<-"&p="
 text3<-"appid="
 savefile<-"c:\\geocode.xml"
 EncodeAddress<-paste(c("",charToRaw(iconv(address,"CP932","UTF-8"))),collapse="%")#なかまさんのURLエンコード
 URLText<-paste(text1,text3,appid,text2,EncodeAddress,sep="")
 download.file(URLText,savefile)
で、c:直下にgeocode.xmlで落ちてきます。xml構造はYahooの方がきれいかも。

**5.RCurlを使う方法( 質問、それって) [#jdabb5f6]
 library(RCurl) # <=  バイナリは腐ってる事もあります
 addr<-"石川県金沢市広坂1丁目1ー1"
 encaddr<-paste(c("",charToRaw(iconv(addr,"","UTF8"))),collapse="%")
 url<-paste("http://maps.google.com/maps?q=",encaddr,"&output=kml",sep="")
 kml<-iconv(getURL(url),"UTF8","")  # iconvの""はカレントのエンコーディングになります
といっしょ?
 addr<-"石川県金沢市広坂1丁目1ー1"
 encaddr<-paste(c("",charToRaw(iconv(addr,"","UTF8"))),collapse="%")
 url<-paste("http://maps.google.com/maps?q=",encaddr,"&output=kml",sep="")
 con<-url(url,encoding="UTF8")
 kml<-readLines(con,warn=F)
でもいいか. 保存するなら
 con<-file("hoge.kml",open="w",encoding="UTF8")
 writeLines(kml,con)
 close(con)

(注:okinawa)RCurlはBioConductorからインストールできます。~

**6.RCurlでまとめてジオコーディング(なかまさん) [#jdabb5f6]
 # ライセンスはGPL!!
 ken<-c("富山市新総曲輪1番7号","金沢市鞍月1丁目1番地","福井市大手3丁目17の1")
 library(XML)
 library(RCurl)
 encaddr<-function(x){sapply(x,function(x)paste(c("",charToRaw(iconv(x,"","UTF8"))),collapse="%"))}
 makeurl<-function(x)sapply(x,function(x)paste("http://maps.google.com/maps?q=",x,"&output=kml",sep=""))
 kmls<-getURIAsynchronous(makeurl(encaddr(ken)))
 
 # encode強制(utf-8の人は何も考えなくて良い)
 kmls<-sapply(kmls,function(x)iconv(x,"UTF-8"))
 kmls<-sapply(kmls,function(x)gsub("encoding=\\\"UTF-8\\\"",
                                   paste("encoding=\\\"",
                                         localeToCharset(),
                                         "\\\"",
                                         sep=""),x))
 
 #nsが見当たらないのでさくっと消す
 kmls<-sapply(kmls,function(x)gsub("<kml xmlns=\\\"http:\\/\\/earth.google.com\\/kml\\/2.0\\\">",
                                   "<kml>",
                                   x))
 
 docs<-sapply(kmls,function(x)xmlTreeParse(x,useInternalNodes=T)) # 内部形式はUTF-8
 
 sapply(docs,function(x)xpathApply(x,"//longitude",xmlValue))
 sapply(docs,function(x)xpathApply(x,"//latitude",xmlValue))
 sapply(docs,function(x)xpathApply(x,"//coordinates",xmlValue))
 sapply(docs,function(x)iconv(xpathApply(x,"//name",xmlValue),"UTF8")) # 日本語はこうして
 sapply(docs,free) # 開放

**7.Yahoo日本語形態素解析APIを利用した住所の形態素解析 [#ed95ba3b]

 library(RCurl) 
 addr<-"沖縄県那覇市久米2丁目4番14号JB-NAHAビル8階"
 encaddr<-paste(c("",charToRaw(iconv(addr,"","UTF-8"))),collapse="%")
 url<-paste("http://api.jlp.yahoo.co.jp/MAService/V1/parse?appid=YahooDemo&results=ma,uniq&uniq_filter=9|10&sentence=",encaddr,sep="")
 kml<-iconv(getURL(url),"UTF-8","")  # iconvの""はカレントのエンコーディングになります
 print(kml)
実行結果(見やすいように整形してあります)
 <?xml version=\"1.0\" encoding=\"UTF-8\" ?>
 <ResultSet xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"urn:yahoo:jp:jlp\" xsi:schemaLocation=\"urn:yahoo:jp:jlp http://api.jlp.yahoo.co.jp/MAService/V1/parseResponse.xsd\">
 <ma_result><total_count>13</total_count>
 <filtered_count>13</filtered_count>
 <word_list>
 <word><surface>沖縄県</surface><reading>おきなわけん</reading><pos>名詞</pos></word>
 <word><surface>那覇市</surface><reading>なはし</reading><pos>名詞</pos></word>
 <word><surface>久米</surface><reading>くめ</reading><pos>名詞</pos></word>
 <word><surface>2</surface><reading>2</reading><pos>名詞</pos></word>
 <word><surface>丁目</surface><reading>ちょうめ</reading><pos>接尾辞</pos></word>
 <word><surface>4</surface><reading>4</reading><pos>名詞</pos></word>
 <word><surface>番</surface><reading>ばん</reading><pos>接尾辞</pos></word>
 <word><surface>14</surface><reading>14</reading><pos>名詞</pos></word>
 <word><surface>号</surface><reading>ごう</reading><pos>接尾辞</pos></word>
 <word><surface>JB-NAHA</surface><reading>JB-NAHA</reading><pos>名詞</pos></word>
 <word><surface>ビル</surface><reading>びる</reading><pos>名詞</pos></word>
 <word><surface>8</surface><reading>8</reading><pos>名詞</pos></word>
 <word><surface>階</surface><reading>かい</reading><pos>接尾辞</pos></word>
 </word_list>
 </ma_result><uniq_result><total_count>13</total_count>
住所もきちんと分解してくれてるようですね。更に、指定した名詞・動詞をフィルタリングして抽出してきてます。
 <filtered_count>9</filtered_count>
 <word_list>
 <word><count>1</count><surface>JB-NAHA</surface><reading/><pos>名詞</pos></word>
 <word><count>1</count><surface>ビル</surface><reading/><pos>名詞</pos></word>
 <word><count>1</count><surface>久米</surface><reading/><pos>名詞</pos></word>
 <word><count>1</count><surface>沖縄県</surface><reading/><pos>名詞</pos></word>
 <word><count>1</count><surface>那覇市</surface><reading/><pos>名詞</pos></word>
 <word><count>1</count><surface>14</surface><reading/><pos>名詞</pos></word>
 <word><count>1</count><surface>2</surface><reading/><pos>名詞</pos></word>
 <word><count>1</count><surface>4</surface><reading/><pos>名詞</pos></word>
 <word><count>1</count><surface>8</surface><reading/><pos>名詞</pos></word>
 </word_list></uniq_result></ResultSet>
並びはどうやって決めてるんだろう?

**8.GoogleMapAPIを用いた逆ジオコーディング [#yd828fdc]
 ##GoogleMapAPIを用いた逆ジオコーディング
 URLText<-"http://maps.google.com/maps/geo?oe=utf-8&ll=35.620519%2C139.438892&key=ABQIAAAA7Qa-RE_JYtVliR9OTauOexScAlgT1OMB91Iojh4cvnPDirRWVBRkKoWJQNoMN19LbzuRx7z0aIWHTQ&output=json&callback=gmap"
 savefile<-"c:\\geocode.xml"
 download.file(URLText,savefile)

*コメント欄 [#g7fc1d05]
#comment(below)
- Yahoo API は有料化 --  &new{2012-12-06 (木) 09:38:20};
- Google Maps の規約変更で、R からの API 利用も問題になる? --  &new{2012-06-06 (水) 11:12:20};
- GoogleMapAPIを用いた逆ジオコーディング追加。ひさびさ。 -- [[okinawa]] &new{2009-02-20 (金) 14:26:07};
- Yahoo 電話帳は API が公開されているのでしょうか? -- [[メルクリンは不滅]] &new{2009-02-09 (月) 21:34:37};
- Yahoo地図ローカルサーチAPIは、24時間中1IPアドレスにつき50000件のリクエストが上限となっています。とのことです。同時アクセスは不明。まあ需要と供給によるんじゃないでしょうか。 -- [[okinawa]] &new{2008-11-20 (木) 15:37:09};
- Google のサービスは同時アクセス40人ほどでエラーになると聞きますが、Yahooの方はどうでしょうか? --  &new{2008-11-20 (木) 14:59:20};

- GoogleAPIkeyもどこぞのサイトのソースを見ればすぐわかりますけどね・・・。人のは使わないようにしましょう。でも、なかまさんの上記のコードにはGoogleAPIkeyは入ってないので、わざわざkey使わなくてもいいんじゃないかな。 -- [[okinawa]] &new{2007-08-03 (金) 17:11:46};
- 確かに、Yahoo は Google よりも太っ腹?  --  &new{2007-08-03 (金) 15:55:11};
- (たぶん)利用できます。 -- [[okinawa]] &new{2007-08-03 (金) 13:28:59};
- YahooMapAPI ですけど、登録IDでなく上にある”YahooDemo”でも利用できるのでしょうか?「 -- [[La,La,La]] &new{2007-08-03 (金) 12:50:05};
- rjsonなるもの発見!jsonをRオブジェクトに変換するものか? -- [[okinawa]] &new{2007-08-01 (水) 08:51:22};
- Yahoo日本語形態素解析APIを用いて住所文字列の分解を行いました。 -- [[okinawa]] &new{2007-06-26 (火) 12:00:10};
- Yahoo Japanから日本語形態素解析WebAPIが公開されました。上記のなかまさんの方法を使うとRから利用できると思います。 -- [[okinawa]] &new{2007-06-19 (火) 09:17:34};
- JNS住所認識システムのjns2conv.exeの学習辞書を起動するとエラーになります。VB5DB.dllが足りないと言われますので、どこぞのサイトからVB5DB.dllを落としてきて、jns2conv.exeと同じフォルダに入れてください。 -- [[okinawa]] &new{2007-06-15 (金) 14:07:27};
- JNS住所認識システム追加(国が出してました。FREEです) -- [[okinawa]] &new{2007-06-15 (金) 11:58:46};
- もうすこし遅い回線(10Mbps)で調べたのですが、件数が60あたりから変換スピードが落ちてきますね。50件づつに分けてやるといいかもしれない。 -- [[okinawa]] &new{2007-06-13 (水) 11:22:56};
 #10Mbps(GoogleMapAPI)
 #10	0.70	0.50	0.58	0.40	0.44
 #20	0.55	0.56	0.51	0.56	0.53
 #30	0.69	0.66	0.68	0.61	0.61
 #40	0.76	0.73	1.08	0.83	0.97
 #50	0.86	0.83	0.87	0.89	1.00
 #60	1.26	1.21	1.11	1.11	1.26
 #70	1.19	1.36	1.52	1.48	1.41
 #80	1.47	1.56	4.05	1.66	1.61
 #90	4.08	4.25	4.24	4.22	4.31
 #100	4.44	4.42	4.54	4.49	4.36
 #150	4.83	5.00	4.78	4.80	5.64
 #200	7.03	5.69	5.42	5.41	5.43
 #300	11.45	13.64	23.22	17.22	11.68

- 上記の街区レベル位置参照情報データから住所データを取り出してGoogleMapAPIでジオコーディングしました。500件で2.8秒これは実用的な速度ですね。 -- [[okinawa]] &new{2007-06-10 (日) 10:05:22};

 [1] 0.597 0.103 4.385 0.000 0.000 #光100M 100件
 [1] 0.949 0.222 3.303 0.000 0.000 #光100M 200件
 [1] 1.400 0.193 3.712 0.000 0.000 #光100M 300件
 [1] 1.833 0.229 3.030 0.000 0.000 #光100M 400件
 [1] 2.211 0.182 2.791 0.000 0.000 #光100M 500件

- 速度と言う意味なら, まとめてやんないとダメだろうけど, 上限はどれくらいだろう住所データ持ちの人っています? -- [[なかま]] &new{2007-06-10 (日) 00:13:44};
 ken<-c("富山市新総曲輪1番7号","金沢市鞍月1丁目1番地","福井市大手3丁目17の1")
 library(RCurl)
 encaddr<-
 function(x){sapply(x,function(x)paste(c("",charToRaw(iconv(x,"","UTF8"))),collapse="%"))}
 makeurl<-
 function(x)sapply(x,function(x)paste("http://maps.google.com/maps?q=",x,"&output=kml",sep=""))
 kmls<-getURIAsynchronous(makeurl(encaddr(ken)))


- 速度計ってみました。結構速い。 (光100M)-- [[okinawa]] &new{2007-06-09 (土) 21:03:24};
 > test<-function(){library(RCurl) 
 + addr<-"沖縄県那覇市久米2丁目4番14号"
 + encaddr<-paste(c("",charToRaw(iconv(addr,"","UTF8"))),collapse="%")
 + url<-paste("http://maps.google.com/maps?q=",encaddr,"&output=kml",sep="")
 + kml<-iconv(getURL(url),"UTF8","")  # iconvの""はカレントのエンコーディングになります
 + print(kml)
 + }
 > system.time(test())
 [1] "<?xml version=\"1.0\" encoding=\"UTF-8\"?><kml xmlns=\"http:(中略)
 [1] 0.008 0.002 0.292 0.000 0.000

- BioConductorからRCurlインストールできました。IntelMacでも動きました。情報ありがとうございました。 -- [[okinawa]] &new{2007-06-09 (土) 13:48:19};
- RCurlはBioConductorのextraからとれますよ. --  &new{2007-06-09 (土) 10:31:52};
- Google のジオコーディングって、住所の後にビル名がつくと処理できないのだっけ。 -- [[荒野の風来坊]] &new{2007-06-09 (土) 10:23:45};
- OmegahatのRCurlを使う方法が追加されました。RCurlは、winは最新で更新されています。MacOSXはppcのみでR2.3まで。Linuxは無いようです。 -- [[okinawa]] &new{2007-06-09 (土) 09:10:49};
- GoogleMapAPIとYahooMapAPIのジオコーディングの比較では、GMは基本的にKMLで落ちてくるので緯度、経度、標高も構造として入っている。(いまのところ0しか入ってないようだが)YMは、日本測地系と世界測地系の2種類のデータが入っており、更にGMより小数点以下の桁数が2桁多い。 -- [[okinawa]] &new{2007-06-08 (金) 18:21:00};
- YahooMapAPIを利用したジオコーディング追加。 -- [[okinawa]] &new{2007-06-08 (金) 18:11:04};
- GoogleMapAPIのGeoCoding?を利用してジオコーディングを追加。なかまさんありがとうございました。 -- [[okinawa]] &new{2007-06-07 (木) 13:37:43};
- 文字列検索アルゴリズムリンク追加 -- [[okinawa]] &new{2007-05-30 (水) 16:04:54};
-皆様からのジオコーディングについての情報を募集しております。 -- [[okinawa]] &new{2007-05-30 (水) 10:02:33};
*アクセス数: [#mb2b3156]
&counter;
人

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS