地球上のすべての地点は、緯度と経度の値で表すことができる。
Wikipediaによると、”ジオコーディングとは、郵便物の住所の記述を地球表面の位置(数値座標による空間表現)に変換する計算処理 “だそうです。
簡単にまとめると、テキストの住所を地球表面上の対応する緯度・経度に表現する処理をジオコーディングと呼んでいます。
今回は、PythonのGeoPyライブラリを使って、住所のジオコードを取得します。
GeoPy
GeoPyはジオコーディングサービスではなく、いくつかの有名なジオコーディングWebサービスのための単なるPythonクライアントです。
それはアドレスのジオコードを見つけるために、サードパーティのジオコーダと他のデータソースを使用します。
下の図は、GeoPyの機能に関するいくつかのアイデアを示しています。
#Importing the Nominatim geocoder class from geopy.geocoders import Nominatim
#address we need to geocode loc = 'Taj Mahal, Agra, Uttar Pradesh 282001'
#making an instance of Nominatim class geolocator = Nominatim(user_agent = "my_request" )
#applying geocode method to get the location location = geolocator.geocode(loc)
#printing address and coordinates print (location.address)
print ((location.latitude, location.longitude))
|
上の図に見られるように、ジオコーディングは多くの異なるサービスによって提供されています。
これらのサービスはAPIを提供し、GeoPyライブラリはこれらのAPIの実装を一つのパッケージで提供します。
geopyが実装するジオコーディングサービスプロバイダの完全なリストは、このドキュメントを参照することができます。
考慮すべきいくつかの重要なポイントがあります。
- ジオコーディングサービスは有料または無料なので、サービスを選択する前に、利用規約、クォータ、価格、ジオデータベースなどに目を通しておいてください。
- ジオコーディングサービスは有料または無料です。
GeoPyが何をするかという高レベルのアイデアは十分なので、次はそれを使って住所のジオコードを取得する方法を見てみましょう。
ジオコーディングサービス
ジオコーディングサービスはたくさんありますが、私はGeocodeAPIがとても気に入りました。
住所から緯度経度を取得するエンドポイントや、逆ジオコーディングのエンドポイントが複数用意されています。
先進的な機能としては、住所のオートコンプリートAPIがある。
部分的な住所から完全な住所を返すこともできる。
また、1日あたり10,000リクエストまで無料で利用できるので、アプリケーションの構築を始めたばかりの方にもおすすめだ。
詳しくは、価格ページで確認できる。
GeoPyを使ったジオコーディング
各ジオロケーションサービス(Nominatimなど)は、サービスのAPIにリンクしている geopy.geocoders
に独自のクラスを持っています。
Geocodersには少なくとも geocode
メソッドがあり、与えられた文字列(ジオコーディングしたい住所)から座標を検索することができます。
このクラスには reverse
メソッドの実装もあり、これは geocode メソッドと逆の動作をします。
ここでは、地表のある点の座標を提供する必要があり、このメソッドは提供された緯度と経度に関連する住所を返す。
1. 住所のジオコードを検索する
この記事では、Nominatimのジオコーディングサービスを使用します。
#Importing the required modules import pandas as pd
from geopy.geocoders import Nominatim
from geopy.extra.rate_limiter import RateLimiter
#Creating a dataframe with address of locations we want to reterive locat = [ 'Coorg, Karnataka' , 'Khajjiar, Himachal Pradesh' ,
'Chail, Himachal Pradesh' , 'Pithoragarh, Uttarakhand' , 'Munnar, Kerala' ]
df = pd.DataFrame({ 'add' : locat})
#Creating an instance of Nominatim Class geolocator = Nominatim(user_agent = "my_request" )
#applying the rate limiter wrapper geocode = RateLimiter(geolocator.geocode, min_delay_seconds = 1 )
#Applying the method to pandas DataFrame df[ 'location' ] = df[ 'add' ]. apply (geocode)
df[ 'Lat' ] = df[ 'location' ]. apply ( lambda x: x.latitude if x else None )
df[ 'Lon' ] = df[ 'location' ]. apply ( lambda x: x.longitude if x else None )
df |
Output:
Taj Mahal, Taj Mahal Internal Path, Taj Ganj, Agra, Uttar Pradesh, 282001, India
(27.1750123, 78.04209683661315)
上のコードを使って、インドのアグラにあるタージマハルの座標を求めました。
Nominatimのクラスには geocode
メソッドがあり、住所の文字列を受け取って、サービスプロバイダのデータベースからその座標を返します。
ジオコードメソッドを使用して返されるオブジェクトは、完全な住所を返す address
メソッドと、その住所の緯度と経度を取得する latitude
、 londitude
メソッドを持っています。
Nominatim geocoder クラスは入力引数として user_agent
を受け取り、 geocoder API にリクエストを送るためのヘッダとして動作します。
2. GeoPy と Pandas Dataframe を使う
RateLimiter` クラスは geocoder クラスのラッパーとして動作し、多くのリクエストを処理する必要がある場合に、サーバへのリクエスト時間を遅延させることができます。
ジオコーディングサービスプロバイダーへのリクエスト数を考慮しながら、複数のリクエストを行わないとエラーになります。
では、インドの美しい自然スポットの住所を持つpandasのデータフレームにこれを適用してみましょう。
RateLimiterクラスは
geocoderクラスオブジェクトと
min_delay_seconds` を入力引数として必要とします。
このメソッドは指定した時間遅延でジオコーディングサービスのサーバーにリクエストをします。
文字列の位置が見つからない場合は自動的に None を返します。
Pandasの.applyメソッドを使用すると、データフレーム上の指定したカラムにラッパーを適用することができます。
この記事もチェック:Pythonのtime.sleepメソッドを使って一定時間だけ処理を止める方法
まとめ
この記事では、ジオコーディングとは何か、そしてpythonのGeoPyライブラリがジオコーディングサービスAPIの簡単な実装をどのように提供しているかを学びました。
また、緯度と経度の座標を得るためにテキストフォーマットの住所をジオコーディングし、住所のカラムを持つpandas DataFrameにこのメソッドを適用しました。