LINK:[GoogleEarthとR][ShapeFileライブラリ][kmlラボ][空間的なデータの分析][Rでジオコーディング][RでGPS]


目次


論文引用・書籍等に引用する場合の著作権についての連絡>>okinawa


目的

GoogleMap?GoogleEarth?のおかげで、最近ジオコーディングという言葉がインターネットで頻繁に使われだしている。
ジオコーディングとは簡単に言えば、住所や郵便番号情報から、緯度・経度の位置情報に変換する技術のことであるが、WebAPIを利用したものや完全にフリーで配布されているもの、有償でかなりお高いものなど多々存在する。
最近になって勢力を拡大してきているのが、WebAPIを利用したジオコーダー(ジオコーディング用のプログラム)で、もっとも有名なのがGoogleMapAPIに含まれているジオコーダーである。
また、国から「街区レベル位置参照情報ダウンロードサービス」が開始されたり、郵便番号データがダウンロードできるようになってからは、これらのデータを組み合わせてジオコーディングを行うものが出てきている。

ここでは、ジオコーディングの情報を収集するとともに、Rを用いたジオコーディングについて検証していくこととする。
基本的には、Rのみでジオコーディングを可能にすることが目標である。
GoogleEarth?のジオコーディングはすばらしいが、なにしろ変換スピードが遅いのがネックである。(ちなみにGoogleMapAPIの日本版ジオコーディング部分はゼンリンのものが使われていると言われている。)

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

利用するパッケージ

RCurl
XML
rjson
SSOAP

ツールとデータ

ジオコーディングツール
無償版:
[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/

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

文字列検索アルゴリズム
[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

日本語形態素解析
[1]YahooJapan?:http://developer.yahoo.co.jp/jlp/MAService/V1/parse.html

RCODE

1.街区レベル位置参照情報データを利用した簡易ジオコーディング

事前に街区レベル位置参照情報ダウンロードサービスから対象となるデータをダウンロードして解凍してください。
下記の例は、沖縄県全域データを利用したものです。

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?を利用したコードが岡田先生により掲載されています。

1)GoogleEarth?を利用したジオコーディング:

# 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にとりこむ関数:

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)を利用してジオコーディング

##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を利用してジオコーディング

##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を使う方法( 質問、それって)

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でまとめてジオコーディング(なかまさん)

# ライセンスは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を利用した住所の形態素解析

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を用いた逆ジオコーディング

##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)

コメント欄


  • Yahoo API は有料化 -- 2012-12-06 (木) 09:38:20
  • Google Maps の規約変更で、R からの API 利用も問題になる? -- 2012-06-06 (水) 11:12:20
  • GoogleMapAPIを用いた逆ジオコーディング追加。ひさびさ。 -- okinawa 2009-02-20 (金) 14:26:07
  • Yahoo 電話帳は API が公開されているのでしょうか? -- メルクリンは不滅? 2009-02-09 (月) 21:34:37
  • Yahoo地図ローカルサーチAPIは、24時間中1IPアドレスにつき50000件のリクエストが上限となっています。とのことです。同時アクセスは不明。まあ需要と供給によるんじゃないでしょうか。 -- okinawa 2008-11-20 (木) 15:37:09
  • Google のサービスは同時アクセス40人ほどでエラーになると聞きますが、Yahooの方はどうでしょうか? -- 2008-11-20 (木) 14:59:20
  • GoogleAPIkeyもどこぞのサイトのソースを見ればすぐわかりますけどね・・・。人のは使わないようにしましょう。でも、なかまさんの上記のコードにはGoogleAPIkeyは入ってないので、わざわざkey使わなくてもいいんじゃないかな。 -- okinawa 2007-08-03 (金) 17:11:46
  • 確かに、Yahoo は Google よりも太っ腹? -- 2007-08-03 (金) 15:55:11
  • (たぶん)利用できます。 -- okinawa 2007-08-03 (金) 13:28:59
  • YahooMapAPI ですけど、登録IDでなく上にある”YahooDemo?”でも利用できるのでしょうか?「 -- La,La,La? 2007-08-03 (金) 12:50:05
  • rjsonなるもの発見!jsonをRオブジェクトに変換するものか? -- okinawa 2007-08-01 (水) 08:51:22
  • Yahoo日本語形態素解析APIを用いて住所文字列の分解を行いました。 -- okinawa 2007-06-26 (火) 12:00:10
  • Yahoo Japanから日本語形態素解析WebAPIが公開されました。上記のなかまさんの方法を使うとRから利用できると思います。 -- okinawa 2007-06-19 (火) 09:17:34
  • JNS住所認識システムのjns2conv.exeの学習辞書を起動するとエラーになります。VB5DB.dllが足りないと言われますので、どこぞのサイトからVB5DB.dllを落としてきて、jns2conv.exeと同じフォルダに入れてください。 -- okinawa 2007-06-15 (金) 14:07:27
  • JNS住所認識システム追加(国が出してました。FREEです) -- okinawa 2007-06-15 (金) 11:58:46
  • もうすこし遅い回線(10Mbps)で調べたのですが、件数が60あたりから変換スピードが落ちてきますね。50件づつに分けてやるといいかもしれない。 -- okinawa 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 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件
  • 速度と言う意味なら, まとめてやんないとダメだろうけど, 上限はどれくらいだろう住所データ持ちの人っています? -- なかま 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 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 2007-06-09 (土) 13:48:19
  • RCurlはBioConductorのextraからとれますよ. -- 2007-06-09 (土) 10:31:52
  • Google のジオコーディングって、住所の後にビル名がつくと処理できないのだっけ。 -- 荒野の風来坊? 2007-06-09 (土) 10:23:45
  • OmegahatのRCurlを使う方法が追加されました。RCurlは、winは最新で更新されています。MacOSXはppcのみでR2.3まで。Linuxは無いようです。 -- okinawa 2007-06-09 (土) 09:10:49
  • GoogleMapAPIとYahooMapAPIのジオコーディングの比較では、GMは基本的にKMLで落ちてくるので緯度、経度、標高も構造として入っている。(いまのところ0しか入ってないようだが)YMは、日本測地系と世界測地系の2種類のデータが入っており、更にGMより小数点以下の桁数が2桁多い。 -- okinawa 2007-06-08 (金) 18:21:00
  • YahooMapAPIを利用したジオコーディング追加。 -- okinawa 2007-06-08 (金) 18:11:04
  • GoogleMapAPIのGeoCoding??を利用してジオコーディングを追加。なかまさんありがとうございました。 -- okinawa 2007-06-07 (木) 13:37:43
  • 文字列検索アルゴリズムリンク追加 -- okinawa 2007-05-30 (水) 16:04:54
  • 皆様からのジオコーディングについての情報を募集しております。 -- okinawa 2007-05-30 (水) 10:02:33

アクセス数:

30182 人


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Google
WWW を検索 OKADAJP.ORG を検索
Last-modified: 2015-03-01 (日) 01:15:59 (1721d)