Reverse Geocoding - Latitude/ Longitude to City/Country - Python and Pandas

Do you need to do reverse geocoding in Python and Pandas. Do you need to convert pairs of latitude and longitude to city, country, address coordinates? If so in this article you can find two different approaches:

  • geocoder
geocoder.osm([51.5074, 0.1278], method='reverse')
  • geopy
geolocator.reverse("48.8588443, 2.2943506")

In the next section you can find more example usage of both methods.

If you need to plot a map from geo coordinates like please check: How to plot latitude and longitude from Pandas DataFrame in Python

Step 1: Install required libraries - geopy and geocoder

First you need to install two libraries geocoder and geopy:

pip install geopy
pip install geocoder

Both libraries offer providers such as Google & Bing which have geocoding services.

geopy and geocoder help to locate the coordinates of addresses, cities, countries, and landmarks across the globe using third-party geocoders and other data sources.

Step 2: Convert latitude and longitude to city/country with geopy

First we will do reverse geocoding with geopy. We are going to retrieve city and state/country about: 51.5074, 0.1278.

We are going to use user_agent="http" otherwise errors will be raised. User_Agent is an http request header that is sent with each request.

The code:

from geopy.geocoders import Nominatim
geolocator = Nominatim(user_agent="http")
location = geolocator.reverse("51.5074, 0.1278")

print(location.address)

this returns:

Fleming Way, London Borough of Bexley, London, Greater London, England, SE28 8NS, United Kingdom

To return the city and the country you can use the next code format:

location.raw.get('address').get('city')

output:

'London'

You can find all fields returned by:

location.raw

which are:

{'place_id': 85508570,
 'licence': 'Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright',
 'osm_type': 'way',
 'osm_id': 5181183,
 'lat': '51.5075415',
 'lon': '0.1280774',
 'display_name': 'Fleming Way, London Borough of Bexley, London, Greater London, England, SE28 8NS, United Kingdom',
 'address': {'road': 'Fleming Way',
  'suburb': 'London Borough of Bexley',
  'city': 'London',
  'state_district': 'Greater London',
  'state': 'England',
  'postcode': 'SE28 8NS',
  'country': 'United Kingdom',
  'country_code': 'gb'},
 'boundingbox': ['51.5071355', '51.5079528', '0.1280173', '0.1292619']}

Step 3: Reverse Geocoding with geocoder

In this step we are going to use geocoder in order to return the information about the:

  • country
  • city
  • zip code / postcode
  • address
  • start

First we will start we getting the city:

import geocoder

g = geocoder.osm([51.5074, 0.1278], method='reverse')
g.json['city']

this will return:

'London'

You can find the whole json result below:

{'accuracy': 0.001,
 'address': 'Fleming Way, London Borough of Bexley, London, Greater London, England, SE28 8NS, United Kingdom',
 'bbox': {'northeast': [51.5079528, 0.1292619],
  'southwest': [51.5071355, 0.1280173]},
 'city': 'London',
 'confidence': 10,
 'country': 'United Kingdom',
 'country_code': 'gb',
 'importance': 0.001,
 'lat': 51.5073599,
 'lng': 0.1283349,
 'ok': True,
 'osm_id': 5181183,
 'osm_type': 'way',
 'place_id': 85508570,
 'place_rank': 26,
 'postal': 'SE28 8NS',
 'quality': 'residential',
 'raw': {'place_id': 85508570,
  'licence': 'Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright',
  'osm_type': 'way',
  'osm_id': 5181183,
  'boundingbox': ['51.5071355', '51.5079528', '0.1280173', '0.1292619'],
  'lat': '51.5073599',
  'lon': '0.1283349',
  'display_name': 'Fleming Way, London Borough of Bexley, London, Greater London, England, SE28 8NS, United Kingdom',
  'place_rank': 26,
  'category': 'highway',
  'type': 'residential',
  'importance': 0.001,
  'address': {'road': 'Fleming Way',
   'suburb': 'London Borough of Bexley',
   'city': 'London',
   'state_district': 'Greater London',
   'state': 'England',
   'postcode': 'SE28 8NS',
   'country': 'United Kingdom',
   'country_code': 'gb'}},
 'region': 'England',
 'state': 'England',
 'status': 'OK',
 'street': 'Fleming Way',
 'suburb': 'London Borough of Bexley',
 'type': 'residential'}

Step 4: Batch Reverse Geocoding with Pandas

Finally let's cover how to reverse geocode with Pandas. We are going to use apply and pass a function which will get as input Latitude and Longitude and will return new column with information for the city:

import geocoder

def geo_rev(x):
    g = geocoder.osm([x.Latitude, x.Longitude], method='reverse').json
    if g:
        return g.get('country')
    else:
        return 'no country'

df[['Latitude', 'Longitude']].apply(geo_rev, axis=1)

result:

United States
United States
           日本
    Indonesia
   no country

In case of an error or point which is not on the land we will return no country.

Step 5: Errors on geocoding with Python

If you try to get result for bad coordinates you will get errors like:

for geocoder

ValueError: Coords are not within the world's geographical boundary

or for geopy

ValueError: Must be a coordinate pair or Point

Resources