都道府県・都市・町情報をテーブル管理したい
はじめに
都道府県・都市・町情報をサービスなどで管理するには、一般的にはGoogle Maps APIなどの力を借りてなるべく自分たちで実装しなくて済むようにするのが一番だと思います(住所などの情報は、頻繁ではないものの更新されていくものなので)
ただ、自前でテーブルを作ったりしないと検索機能をつくれなかったり、機械学習の特徴量として位置情報を利用したかったりなどの場合にはどうしても必要になるタイミングがあると思います。
政府統計の境界データ
政府統計のe-Statというサイトがあり、ここでは各町毎の境界データがダウンロードできます。
今回は東京都全域の境界データをみていきます。
shapeファイル
まずzipを解凍すると、見た事のない拡張子が並んでますが、これはすべて必要みたいです。
これらを総称してshapeファイルという(嘘だったらすみません)みたいですが、今回はこのファイルをPythonで扱いたいので必要なパッケージをインストールしていきます。
pip install pyshp shapely
もっと楽にデータの中身をみたい、という方はshapeファイルをpandasのデータフレームのように扱えるgeopandasというパッケージもインストールしておくと便利だと思います。
pip install geopandas
試しにgeopandasでshapeファイルを読み込んでみましょう。
import geopandas as gpd
df = gpd.read_file('h27ka13.shp')
こんな感じのデータになっていると思います。
ざっくりと必要なカラムについての説明をすると、
- PREF: 都道府県ID(2桁)
- CITY: 都市ID(3桁)
- S_AREA: 町ID(6桁)
- PREF_NAME: 都道府県名
- CITY_NAME: 都市名
- S_NAME: 町名
- geometry: 境界データ(Polygon)
です。(おそらくS_NAME
のS
はSTREETのSだと思われます)
地域情報テーブル
そのため、サービスとしてテーブルをつくるのであれば、
-
prefectures
テーブル -
cities
テーブル -
streets
テーブル
を用意すれば良いかと思われます。
あとは、ある地点の緯度経度からprefecture_id
, city_id
, street_id
を導くことができればすべての住所がテーブル管理できます。
prefecture_id
, city_id
, street_id
はそれぞれ桁数が2
, 3
, 6
と決まっているのでこれらを文字列として連結したものを緯度経度から取得できればいいことになります。(これをAddressCode
と呼ぶことにします)
緯度経度と各テーブルの紐付け
ある緯度経度がある町に含まれているということは、その町の境界データgeometryに含まれていることと同値なので、AddressCode
を緯度経度から取得するスクリプトをつくりました。
import shapefile
from shapely.geometry import shape, Point
class AddressCodeGetter:
def __init__(self, shp_path: str, encoding='cp932'):
"""shapeファイルを指定して読み込む."""
r = shapefile.Reader(shp_path, encoding=encoding)
self.shapes = r.shapes()
self.records = r.records()
def getAddressCode(self, latitude: float, longitude: float):
"""指定した緯度経度を含むPolygonを見つけて、そのAddressCodeを返す."""
point = Point(longitude, latitude)
AddressCode = ''
for i in range(len(self.shapes)):
polygon = shape(self.shapes[i])
if polygon.contains(point):
AddressCode = ''.join(self.records[i][1:4]) # PREF, CITY, S_AREAを文字列連結
break
return AddressCode
code = AddressCodeGetter('h27ka13.shp')
# 六本木ヒルズ森タワー(東京都港区六本木6丁目)
code.getAddressCode(35.660477, 139.729356) # '13103017006'
# 東京都庁(東京都新宿区西新宿2丁目)
code.getAddressCode(35.689604, 139.692305) # '13104094002'
# 皇居(東京都千代田区千代田)
code.getAddressCode(35.685756, 139.752292) # '13101014000'
# 渋谷スクランブルスクエア(東京都渋谷区渋谷2丁目)
code.getAddressCode(35.658778, 139.702487) # '13113010002'
これによって、経度経度からその地点のprefecture_id
, city_id
, street_id
が求められることになりました。
例えば東京都庁の場合は、AddressCodeが13104094002
なので
{
"prefecture_id": 13,
"city_id": 104,
"street_id": 94002
}
となります(street_idは094002
なので数値化すると94002
となる)
おわりに
ある地点のAddressCodeを取得する際、緯度経度から取得するやり方ではなく住所から文字列操作によって行うやり方もありますが、これは結構大変です。意外と町名が最近変わっていたり、市町村合併されていたり、ユーザが入力した住所に旧字体が使われていたために認識できなかったり..など
特にユーザ入力させた住所をテーブルと紐付けるときには、Goole Maps APIから帰ってきた緯度経度を用いてAddressCodeを算出するなどして既存のAPIをうまく併用しながら開発すると快適なGeoライフが送れると思います!
Author And Source
この問題について(都道府県・都市・町情報をテーブル管理したい), 我々は、より多くの情報をここで見つけました https://qiita.com/s2hap/items/4b918a33c1b77c6e43f9著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .