GeoPandasのジオコーディングのプロバイダー(Gecoder)を指定してみた

2022.08.31

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部 IoT事業部の若槻です。

GeoPandasは、pandasで使われているデータ形式であるDataFrameを、地理空間データの操作をできるように拡張したライブラリです。

このGeoPandasではジオコーディング(地名やランドマーク名から緯度/経度への変換)の機能もあるのですが、その際に使用されるプロバイダーは任意のものを指定することが可能です。

今回は、GeoPandasでジオコーディングのプロバイダー(Gecoder)を指定する方法を確認してみました。

やってみる

環境

$ python3
Python 3.10.6 (main, Aug 11 2022, 13:36:31) [Clang 13.1.6 (clang-1316.0.21.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import geopandas
>>> geopandas.__version__
'0.11.1'
>>> import geopy
>>> geopy.__version__
'2.2.0'

GeoPandasやGeopyの詳しい導入方法は前回のエントリ(M1 Macの場合)または公式ドキュメントをご覧ください。

使用可能なGeocoder一覧の確認

geopy.geocoders.SERVICE_TO_GEOCODERで使用可能なGeocoder名とクラスの対応一覧を確認できます。

>>> geopy.geocoders.SERVICE_TO_GEOCODER
{'algolia': <class 'geopy.geocoders.algolia.AlgoliaPlaces'>, 'arcgis': <class 'geopy.geocoders.arcgis.ArcGIS'>, 'azure': <class 'geopy.geocoders.azure.AzureMaps'>, 'baidu': <class 'geopy.geocoders.baidu.Baidu'>, 'baiduv3': <class 'geopy.geocoders.baidu.BaiduV3'>, 'banfrance': <class 'geopy.geocoders.banfrance.BANFrance'>, 'bing': <class 'geopy.geocoders.bing.Bing'>, 'databc': <class 'geopy.geocoders.databc.DataBC'>, 'geocodeearth': <class 'geopy.geocoders.geocodeearth.GeocodeEarth'>, 'geocodio': <class 'geopy.geocoders.geocodio.Geocodio'>, 'geonames': <class 'geopy.geocoders.geonames.GeoNames'>, 'google': <class 'geopy.geocoders.google.GoogleV3'>, 'googlev3': <class 'geopy.geocoders.google.GoogleV3'>, 'geolake': <class 'geopy.geocoders.geolake.Geolake'>, 'here': <class 'geopy.geocoders.here.Here'>, 'herev7': <class 'geopy.geocoders.here.HereV7'>, 'ignfrance': <class 'geopy.geocoders.ignfrance.IGNFrance'>, 'mapbox': <class 'geopy.geocoders.mapbox.MapBox'>, 'mapquest': <class 'geopy.geocoders.mapquest.MapQuest'>, 'maptiler': <class 'geopy.geocoders.maptiler.MapTiler'>, 'nominatim': <class 'geopy.geocoders.nominatim.Nominatim'>, 'opencage': <class 'geopy.geocoders.opencage.OpenCage'>, 'openmapquest': <class 'geopy.geocoders.openmapquest.OpenMapQuest'>, 'pickpoint': <class 'geopy.geocoders.pickpoint.PickPoint'>, 'pelias': <class 'geopy.geocoders.pelias.Pelias'>, 'photon': <class 'geopy.geocoders.photon.Photon'>, 'liveaddress': <class 'geopy.geocoders.smartystreets.LiveAddress'>, 'tomtom': <class 'geopy.geocoders.tomtom.TomTom'>, 'what3words': <class 'geopy.geocoders.what3words.What3Words'>, 'what3wordsv3': <class 'geopy.geocoders.what3words.What3WordsV3'>, 'yandex': <class 'geopy.geocoders.yandex.Yandex'>}

分かりやすく並べてみます。標準で31種類も使えるんですね。(ただしgooglegooglev3は同じクラスを指しているなど重複はあります。)

>>> geocoders = geopy.geocoders.SERVICE_TO_GEOCODER.keys()
>>> for mykey in geocoders:
      print(mykey)
...
algolia
arcgis
azure
baidu
baiduv3
banfrance
bing
databc
geocodeearth
geocodio
geonames
google
googlev3
geolake
here
herev7
ignfrance
mapbox
mapquest
maptiler
nominatim
opencage
openmapquest
pickpoint
pelias
photon
liveaddress
tomtom
what3words
what3wordsv3
yandex
>>> len(geocoders)
31

ジオコーディングしてみる

それでは各種Geocoderを使ってジオコーディングを試してみます。

構文は下記のようになります。

geopandas.tools.geocode(strings, provider=None, **kwargs)

ちなみに第2引数のproviderの指定は、前節で確認したGeocoder名もしくはクラスの直接指定のいずれでも可能です。例えばAlgoliaなら次の2通りが可能です。お好きな方をどうぞ。

>>> geopandas.tools.geocode("東京都", "algolia")
>>> geopandas.tools.geocode("東京都", geopy.geocoders.algolia.AlgoliaPlaces)

指定なし(Photon)

Geocoderが未指定の場合、既定ではPhotonが使われます。PhotonはOpenStreetMap上での検索APIを提供します。

検索対象の地名やランドマークをいくつか試してみます。

>>> geocoder = None
>>> geopandas.tools.geocode("東京都", geocoder)
                     geometry                                            address
0  POINT (135.53399 34.69673)  京橋, Higashi Nodamachi, 534-0025, Higashi Nodam...

>>> geopandas.tools.geocode("東京都千代田区", geocoder)
                   geometry address
0  GEOMETRYCOLLECTION EMPTY    None

>>> geopandas.tools.geocode("東京都千代田区九段南1-2-1", geocoder)
                   geometry address
0  GEOMETRYCOLLECTION EMPTY    None

>>> geopandas.tools.geocode("東京タワー", geocoder)
                     geometry                      address
0  POINT (139.74893 35.70054)  タワー飯田橋通り, 102-0072, 東京都, 日本

>>> geopandas.tools.geocode("Tokyo, Japan", geocoder)
                     geometry  address
0  POINT (139.75945 35.68284)  東京都, 日本

>>> geopandas.tools.geocode("Chiyoda-Ku, Tokyo, Japan", geocoder)
                     geometry                                            address
0  POINT (139.76124 35.68450)  パレスホテル東京, 1-1-1 Marunouchi, Chiyoda-ku, Tokyo,...

Photonでは日本の地名や住所だと日本語の場合は上手くジオコーディングが行われず、英語だと行われるようです。(なぜパレスホテル東京なのかは謎ですが)東京タワーのジオコーディングも場所がずれています。

指定した場合(Algolia)

次にGeocoderを指定した場合の例としてAlgoliaを試してみます。Algoliaは検索エンジン機能が有名ですが、ジオコーディング機能も提供しているんですね。

前節と同じ検索対象で試してみます。

>>> geocoder = geopy.geocoders.algolia.AlgoliaPlaces

>>> geopandas.tools.geocode("東京都", geocoder)
                     geometry address
0  POINT (139.75900 35.68280)     東京都

>>> geopandas.tools.geocode("東京都千代田区", geocoder)
                   geometry address
0  GEOMETRYCOLLECTION EMPTY    None

>>> geopandas.tools.geocode("東京都千代田区九段南1-2-1", geocoder)
                   geometry address
0  GEOMETRYCOLLECTION EMPTY    None

>>> geopandas.tools.geocode("東京タワー", geocoder)
                     geometry address
0  POINT (139.74500 35.65860)   東京タワー

>>> geopandas.tools.geocode("Tokyo, Japan", geocoder)
                     geometry                 address
0  POINT (139.77700 35.62940)  Tokyo Trick Art Museum

>>> geopandas.tools.geocode("Chiyoda-Ku, Tokyo, Japan", geocoder)
                   geometry address
0  GEOMETRYCOLLECTION EMPTY    None

Algoliaは日本の地名や住所は日本語および英語のいずれでもジオコーディングが行われないようです。しかしランドマーク東京タワーは上手くできています。

アクセスキーが必要なものもある

ちなみに一部のGeocoderはAPIを叩くためのアクセスキーを指定しないと使えません。Geocoderのサービス側で事前に取得しておく必要があります。

いくつか試してみたところ次のGeocoderでアクセスキーが必要でした。

  • azure
  • bing
  • googlev3
  • here
  • herev7
  • mapbox
  • what3words
  • what3wordsv3

これらのGeocoderでアクセスキー未指定の場合は次のようにエラーとなります。

>>> geopandas.tools.geocode("東京タワー", geopy.geocoders.bing.Bing)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/homebrew/lib/python3.10/site-packages/geopandas/tools/geocoding.py", line 67, in geocode
    return _query(strings, True, provider, throttle_time, **kwargs)
  File "/opt/homebrew/lib/python3.10/site-packages/geopandas/tools/geocoding.py", line 136, in _query
    coder = provider(**kwargs)
TypeError: Bing.__init__() missing 1 required positional argument: 'api_key'

おわりに

GeoPandasでジオコーディングのプロバイダー(Gecoder)を指定する方法を確認してみました。

フリーで使えるサービスのGecoderだと日本に対応していない場合も多いようで、AzureやGoogleを有償利用するなどした方が良さそうです。what3words(ある地点を3つのワードで指定できる)は気になるので次回以降試してみたいです。

以上