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