概要
住所から地図上の位置情報(緯度、経度)を求めることをジオコーディング、その逆に地図上の位置情報から住所を求めることを逆ジオコーディング(リバース ジオコーディング)というらしい。
そんな面倒な処理は、普通Google Geocoding APIなんかの外部のサービスを利用すればよいのだけど、そういうのが使えない状況ってのがたまにある。さてどうするかというのが今回の問題。
結果としては、国土交通省が位置参照情報ダウンロードサービスで提供している街区レベル位置参照情報を使って自前で準備する。後は良しなに。もちろんいろいろな制約もある。
参考にしたのは以下
– 逆ジオコーディング 緯度経度から住所へ変換する
– ジオコーディングと逆ジオコーディングをする方法(Google Geocoding APIの使い方)
– OpenStreetMapでジオコーディング †
– 各種ジオコーディングapiの罠と対処法
特に制約なく使えそうなものとしてOpenStreetMapのNominatimというジオコーディングのWebAPIもあるが、あれはちょっと違う。どうも近くの通りの名前をベースに引いてくるらしいので、日本的な住所を調べるには少し方向が違う。
やってみる
まずは、なにはなくとも街区レベル位置参照情報を位置参照情報ダウンロードサービスからダウンロードする。例えば、都道府県単位を選択し、ダウンロードしたいところを選択、そのうち「街区」レベルにチェックを入れてダウンロード。
福岡県の場合、だいたい3.5MB程度のzipファイルがダウンロードされるはず。重要なのは中にあるcsvファイル。展開するとだいたい24MBくらい。中身は後述の様なフィールドに分かれている。重要なのは住所に関する項目と緯度経度。それ以外のフィールドは必要に応じて利用する。これらのフィールドをDBなどに格納して検索すれば良い。
もっとも近い住所を取得したいので、SQL的には例えば以下の様なものになる。
SELECT *, ( abs(緯度1 - 緯度2) + abs(経度1 - 経度2)) as d
FROM locations
ORDER BY d ASC LIMIT 1;
逆に、住所から位置情報を取得したい(ジオコーディング)場合は逆に引けばいい。ただし、街区レベル位置参照情報の住所の正規化みたいな話はしておかないと中々満足な結果は出ないかも。とは言っても今回は特に必要ないのであまり考えない。
結果と感想
簡単に作って試してみたところ、おおむね位置情報から住所を取得できるようになった。もちろん正確な住所のエリアを持っているわけではないため、それぞれに単純に一番近い住所を引っ張ってきている。
なので、変則的な形をしている町丁目だったり、複数の間に位置するような地点だと若干のズレが確認できる。このズレが許容できるかどうかは個別に判断するべきこと。
とは言っても元ネタになるデータの問題でもあるので、より細かい情報があれば改善できるだろう。どっかにあれば良いのだけど。
また、データの更新についても自前で準備するものである以上自分でやる必要がある。そうそう変わるものではないと思うが、ある程度考えておかないと「は?」って結果が出てきそうな感じ。
日本全国でやろうとすると検索速度なんかも問題になってくるがその辺はDBの問題なので今は考えない。急ぐならPostgreSQL+PostGISとか使うと良いんじゃないかな。海外についても今は考えない。簡単に単純にやろう。
ちなみになにも考えずに以下の様なテーブルを作ってSqlite3にぶち込んだら25MB程度になった。もとのCSVがそのくらいの容量なのでそんなもんかな。都道府県名や住所の正規化をせずにそのまま文字列で放り込んでいるので、そんなもんと言われればそんなもんなのかもしれない。
CREATE TABLE "locations" (
`都道府県名` TEXT,
`市区町村名` TEXT,
`大字・町丁目名` TEXT,
`緯度` REAL,
`経度` REAL
)
街区レベル位置参照情報のデータ項目
項目 | 備考 |
---|---|
都道府県名 | |
市区町村名 | 郡部は郡名、政令指定都市の区名も含む。 |
大字・町丁目名 | 町丁目の数字は漢数字 |
街区符号・地番 | 原則として半角整数(一部漢字等あり) |
座標系番号 | 平面直角座標系の座標系番号(1~19:半角整数) |
X座標 | 平面直角座標系の座標系原点からのずれ |
Y座標 | 平面直角座標系の座標系原点からのずれ |
緯度 | 十進経緯度(単位:度、小数点以下第6位まで) |
経度 | 十進経緯度(単位:度、小数点以下第6位まで) |
住居表示フラグ | 1:住居表示実施、0:住居表示未実施 |
代表フラグ | 1つの街区符号が複数の代表点に対応付けられる場合などに、そのうちの1つに便宜的に代表フラグを立てています。 |
更新前履歴フラグ | 2007年度および2008年度データに含まれるフラグを立てています。 |
更新後履歴フラグ | 2009年度以降のデータに含まれるフラグを立てています。 |