[PYTHON] Get the address from latitude and longitude

We will publish a program that searches for polygons containing certain coordinates using the published polygon data. Getting an address from latitude and longitude is called Reverse geocoding.

If you don't have polygon data, Reverse geocoding is also provided by Google Maps API etc. and it is easy to use. If you have polygon data and want to reverse geocode, you can also use the GIS function of a database such as MySQL.

This time, it is a Python program when you want to determine which city, ward, town, or village in Japan belongs to a large number of coordinates. Even a small fish program that generates an index every time has many coordinates, so it took less time to execute than when using MySQL 5.6.

Benefits of using MySQL:

--If you have data, just put the data and write SQL

Demerit:

--You need polygon data that matches the address level you want (address level polygons may not be available easily)

Why implemented in Python:

――You don't have to be as detailed as the address level --When you access the database, the amount is too large to finish (of course, API is also difficult) --The source of the area data used for verification is clear

Required library

`pip install rtree shapely` alone may not work because there are dependent libraries. So please read each document for installation.

Matching addresses from latitude and longitude

You can write this using rtree and shapely.

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)Create a Rtree from an iterator that returns

        Polygon.Rtree created based on bound holds id and Polygon.

        Args:
            itr: (id, Polygon)Iterator that returns
        '''
        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)Polygon area including_Returns id.

If it matches two or more Polygons, it is sorted and returned in ascending order of area.
(When there is an area that has an inclusion relationship, it is better to select the one with the smaller area.
However, in reality, there is an overlap between Polygon and 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))

How to use

This is the case when using boundary data that can be downloaded from e-stat.

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 that returns'''
    with fiona.open(shapefile, 'r') as source:
        for obj in source:
            #Polygon data
            polygon = shape(obj['geometry'])

            #Address of the area
            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)

            #Generate a unique 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)

    #Make an 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()

Execution example:

$ 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, Shozokumachi, Iwakuni City, Yamaguchi Prefecture

Comparison with other similar libraries

Recommended Posts

Get the address from latitude and longitude
Get the address from the zip code
Obtain location information (latitude and longitude) from the address. Geocode in Python ~ Geocoder and pydams ~
Find the distance from latitude and longitude (considering the roundness of the earth).
Find the waypoint from latitude and longitude (considering the roundness of the earth).
Download Geographical Survey tiles from latitude and longitude
How to get the pixel value of the point from the satellite image by specifying the latitude and longitude
Give latitude and longitude point sequence data and try to identify the road from OpenStreetMap data
How to get followers and followers from python using the Mastodon API
Get the client's IP address in Django
Get wordpress posts from the past week
[Python] Get the main color from the screenshot
Get only the text from the Django form.
[GPS] Use pyproj to calculate distance, azimuth, and elevation from GPS latitude and longitude
Get the contents of git diff from python
Get the module itself and add members dynamically
Get latitude / longitude distance in meters with QGIS
Get only the address part of NIC (eth0)
Get popular tweets from the Twitter timeline, list them and graduate from Tsui Abolition
Pass an array from PHP to PYTHON and do numpy processing to get the result
Get the title of yahoo news and analyze sentiment
[Python] Get the text of the law from the e-GOV Law API
Get the return code of the Python script from bat
[2020 version] Scraping and processing the text from Aozora Bunko
Get nearby latitude / longitude points with Python's geoindex library
Approximately 200 latitude and longitude data for hospitals in Tokyo
Get comments and subscribers with the YouTube Data API
Get mail from Gmail and label it with Python3
[Django 2.2] Sort and get the value of the relation destination
Get files from Linux using paramiko and scp [Python]
YOLP: Extract latitude and longitude with Yahoo! Geocoder API.
[Linux] [C / C ++] How to get the return address value of a function and the function name of the caller
Get the GNOME version
Get the MIME Type
Get an image from a web page and resize it
DJango Note: From the beginning (simplification and splitting of URLConf)
Read the function name from the DB and execute it dynamically
Get your heart rate from the fitbit API in Python!
Get and create nodes added and updated in the new version
Beginners get Qiita tag information and visualize and consider the TOP10.
Get the MIME type in Python and determine the file format
Implement location retrieval by latitude and longitude using Redis and redis-py
Search for variables in pandas.DataFrame and get the corresponding row.
Get the value while specifying the default value from dict in Python
How to get all the keys and values in the dictionary
I tried to get various information from the codeforces API
Make a BLE thermometer and get the temperature with Pythonista3
Get the weather using the API and let the Raspberry Pi speak!
I want to get information from fstab at the ssh connection destination and execute a command
[Map display] Display a map from the address registered by the user using the Google Maps JavaScript API and Geocoding API!
Get information from the Japan Meteorological Agency and notify Slack of weather warnings in the 23 wards of Tokyo
To get a local IP address programmatically
Get the client's IP address in Django
Get your own IP address in Python
Convert IP address to decimal
Get the address from the zip code
How to get IP when Tornado + nginx
Get a local DynamoDB environment with Docker
Translate IP address range to another subnet 1: 1
Get the address from latitude and longitude