Wir werden ein Programm veröffentlichen, das anhand der veröffentlichten Polygondaten nach Polygonen sucht, die bestimmte Koordinaten enthalten. Das Abrufen einer Adresse aus Längen- und Breitengrad wird als umgekehrte Geokodierung bezeichnet.
Wenn Sie keine Polygondaten haben, wird die umgekehrte Geokodierung auch von der Google Maps-API usw. bereitgestellt und ist einfach zu verwenden. Wenn Sie über Polygondaten verfügen und die umgekehrte Geokodierung durchführen möchten, können Sie auch die GIS-Funktion einer Datenbank wie MySQL verwenden.
Diesmal handelt es sich um ein Python-Programm, mit dem Sie bestimmen möchten, welche Stadt, Gemeinde, Stadt oder welches Dorf in Japan zu einer großen Anzahl von Koordinaten gehört. Selbst ein kleines Fischprogramm, das jedes Mal einen Index generiert, hat viele Koordinaten, sodass die Ausführung weniger Zeit in Anspruch nahm als bei Verwendung von MySQL 5.6.
Vorteile der Verwendung von MySQL:
Fehler:
――Sie benötigen Polygondaten, die der gewünschten Adressenebene entsprechen (Polygone auf Adressenebene sind möglicherweise nicht einfach verfügbar).
Grund für die Implementierung in Python:
――Sie müssen nicht so detailliert sein wie die Adressenebene
`Pip install rtree shapeely
`allein funktioniert möglicherweise nicht, da abhängige Bibliotheken vorhanden sind. Lesen Sie daher bitte jedes Dokument zur Installation.
Sie können dies mit rtree und Shapely schreiben.
revgeocoder.py
# -*- coding: utf-8 -*-
import collections
from shapely.geometry import Polygon, Point
from rtree import index
Area = collections.namedtuple('Area', ['area_id', 'polygon'])
class ReverseGeocoder():
def __init__(self):
self.idx = index.Index()
def insert_from_iterator(self, itr):
'''(id, Polygon)Erstellen Sie einen Rtree aus einem Iterator, der zurückgibt
Polygon.Rtree basierend auf gebundenen Holds ID und Polygon erstellt.
Args:
itr: (id, Polygon)Iterator, der zurückkehrt
'''
for i, (area_id, polygon) in enumerate(itr):
obj = Area(area_id=area_id, polygon=polygon)
self.idx.insert(i, polygon.bounds, obj)
def contains(self, lat, lon):
'''Point(lat, lon)Polygonbereich einschließlich_Gibt die ID zurück.
Wenn es mit zwei oder mehr Polygonen übereinstimmt, wird es sortiert und in aufsteigender Reihenfolge der Fläche zurückgegeben.
(Wenn es einen Bereich gibt, der eine Einschlussbeziehung hat, ist es besser, den mit dem kleineren Bereich auszuwählen.
In Wirklichkeit gibt es jedoch eine Überlappung zwischen Polygon und Polygon ... )
'''
result = []
point = Point(lat, lon)
for hit in self.idx.intersection(point.bounds, objects=True):
if hit.object.polygon.contains(point):
result.append(hit.object)
if len(result) > 1:
result.sort(key=lambda x: (x.polygon.area, x.area_id))
return [r.area_id for r in result]
def __repr__(self):
return '<ReverseGeocoder contains {} polygons>'.format(self.idx.count(self.idx.bounds))
Wenn Sie die Grenzdaten verwenden, die von e-stat heruntergeladen werden können, sieht dies folgendermaßen aus.
findcity.py
# -*- coding: utf-8 -*-
import glob
import fiona
from shapely.geometry import Polygon, shape
from revgeocoder import ReverseGeocoder
def parse_shapefile(shapefile):
'''(area_id, Polygon, name)Generator, der zurückgibt'''
with fiona.open(shapefile, 'r') as source:
for obj in source:
#Polygondaten
polygon = shape(obj['geometry'])
#Adresse des Gebiets
names = []
for prop in ['KEN_NAME', 'GST_NAME', 'CSS_NAME', 'MOJI']:
if obj['properties'][prop] is not None:
names.append(obj['properties'][prop])
name = ''.join(names)
#Generieren Sie eine eindeutige ID (KEN+ CITY + SEQ_NO2)
area_id = int(''.join(map(str, (obj['properties']['KEN'], obj['properties']['CITY'], obj['properties']['SEQ_NO2']))))
yield area_id, polygon, name
def main():
shapefiles = glob.glob('data/japan-shape/A002005212010DDSWC3520*/*.shp')
print('Shapefiles:', shapefiles)
#Machen Sie einen Index
rgeocoder = ReverseGeocoder()
id2name = {}
def gen(shapefile):
for area_id, polygon, name in parse_shapefile(shapefile):
id2name[area_id] = name
yield area_id, polygon
for shapefile in shapefiles:
rgeocoder.insert_from_iterator(gen(shapefile))
# test
area_id = rgeocoder.contains(132.257269, 34.108815)[0]
print(area_id, id2name[area_id])
return rgeocoder
if __name__ == '__main__':
rgeocoder = main()
Ausführungsbeispiel:
$ python findcity.py
Shapefiles: ['data/japan-shape/A002005212010DDSWC35208/h22ka35208.shp', 'data/japan-shape/A002005212010DDSWC35207/h22ka35207.shp', 'data/japan-shape/A002005212010DDSWC35201/h22ka35201.shp', 'data/japan-shape/A002005212010DDSWC35203/h22ka35203.shp', 'data/japan-shape/A002005212010DDSWC35206/h22ka35206.shp', 'data/japan-shape/A002005212010DDSWC35202/h22ka35202.shp', 'data/japan-shape/A002005212010DDSWC35204/h22ka35204.shp']
35208602 6-chome, Sofucho, Stadt Iwakuni, Präfektur Yamaguchi
Recommended Posts