★データ解析備忘録★

ゆる〜い技術メモ

【R】OSMのNominatimでAPIを使わずに緯度経度から都道府県と市を求める(スモールデータ向きお手軽版)

はじめに

Rで逆ジオコーディングをやるやり方は、以下のようなやり方が提案されています。

qiita.com

qiita.com

ただし、いずれも速度面や正確さの面で問題があると記事内でも言及されています。

OSMのNominatim

OSM(Open Street Map)は、{leaflet}パッケージでもデフォルトの地図として使われているオープンソースの地図です。 このOSMが提供しているAPIのようなものに、Nominatimがあります。

NominatimをRで操作するパッケージは既に公開されていますし日本語での紹介記事もありますが、NominatimのAPI1を取得せねばならず、これには月間15,000リクエストの制限があるようです。

Nominatimは、直接URLを入力すればブラウザ上で逆ジオコーディングの結果をXMLまたはJSON形式で取得できます。(引数の詳細はJA:Nominatim - OpenStreetMap Wiki) たとえば、

http://nominatim.openstreetmap.org/reverse?format=xml&lat=35.626065&lon=139.884678&zoom=18&addressdetails=1

というURLに対しては以下のような結果が返ってきます。 f:id:songcunyouzai:20170706230031p:plain

これをRで操作できれば、APIを使わなくても逆ジオコーディングができそうです。

Rでやってみる

RでWebのデータを操作するパッケージは様々ありますが、やはり{rvest}を使うのが最もお手軽でしょう。

今回はNominatimでXML形式で結果を出すことにしたので、 xml2::read_xml() 関数2をベースに find_pref_city() という関数を作成してみました。もちろんJSONで出力しても同じようなことはできます。

library(rvest)
library(stringr)

find_pref_city <- function(lat, lon) {
  nominatim_url <- str_c("http://nominatim.openstreetmap.org/reverse?format=xml&lat=",
                          lat,
                          "&lon=",
                          lon,
                          "&zoom=18&addressdetails=1")
  xmldata <- read_xml(nominatim_url)
  pref <- xmldata %>%
    xml_nodes(xpath = "/reversegeocode/addressparts/state") %>%
    xml_text()
  city <- xmldata %>%
    xml_nodes(xpath = "/reversegeocode/addressparts/city") %>%
    xml_text()
  res <- str_c(pref, city)
  return(res)
}

緯度と経度を引数にして都道府県と市を出力します。

> find_pref_city(35.626065, 139.884678)
[1] "千葉県浦安市"
> find_pref_city(35.039200, 135.728965)
[1] "京都府京都市"
> find_pref_city(35.658739, 139.673676)
[1] "東京都世田谷区"

速度もネットを介してる割には速いと思います。

> system.time(find_pref_city(35.626065, 139.884678))
   ユーザ   システム       経過  
     0.003      0.000      0.561 

ちなみに

ブラウザ上の結果を見ればわかりますが、東京ディズニーシーとかなり細かいところまで出力してくれます。 xpathのところをいじれば、いろんな情報が楽にとれますね。

注意

  • OSMはデフォルトでは入力の緯度経度に一番近い「通り」ベースで検索をしてるらしいので細かいところはたまに間違うことはあるみたいですが、都道府県や市のレベルだと概ね問題なさそうです。
  • ネットを介してOSMにリクエストを送っているので、当然ながら一気にリクエストを送りすぎると拒否られると思います。 現在、OSMの逆ジオコーディングをローカルでできないか模索中です。

  1. https://developer.mapquest.com/

  2. {xml2}は{rvest}の依存パッケージで、 xml_text() も{xml2} の関数です。