How to do a Reverse Address Lookup using Latitude and Longitude in Python

A reverse address lookup uses the longitude and latitude to find the address.

Let’s say you have a DataFrame full of longitudes and latitudes and need to get the address information associated with each. Here’s an example:

df = pd.DataFrame([[38.8976763,-77.0387185],[40.7484405,-73.9878531],[48.8606111,2.337644]], columns=['latitude', 'longitude'])
df

To convert those to an address, we can use geopy Python package and the Google Maps API. To get started, you’ll need to sign up for a Google Cloud account and request an API key. It’s free to sign up for the Google Cloud Platform. They have a pretty generous free tier, however, If you are trying to convert a lot of addresses, I would look into pricing. Here is what you’ll need to do to get started:

  1. Get an API key from Google. Follow these instructions.
  2. Enable the Geocoding API. You can simply search for it using the top menu search bar in the Google Cloud Console.

Now you are all set to return back to Python. You’ll import the following libraries and insert your API key.

import geopandas as gpd
import geopy

from geopy.geocoders import GoogleV3
geolocator = GoogleV3(api_key='')

To test it out, get input the longitude and latitude, run the geolocator.reverse function, then view the entire details of the address using address.raw. Here is an example using the latitude and longitude of the Empire State Building that I got from Google Maps. The longitude and latitude are in the address bar of your google maps search result.

point = [40.7483811,-73.9898062]
address = geolocator.reverse(point,exactly_one=True)
address.raw

If successful, you’ll get a bunch of JSON data with the results! The next step is to convert this to a function and append the data to your DataFrame. To isolate the long_name from the data, use the following code:

pd.json_normalize(address.raw['address_components']).explode(column='types').drop_duplicates(subset=['types']).set_index('types')['long_name']

Breaking this Down

Let’s take a closer look at each component of the previous code.

Convert the Data to a DataFrame

Using pd.json_normalize we can easily convert the data to a DataFrame. However, you’ll notice that the types column is a list.

convert_to_json = pd.json_normalize(address.raw['address_components'])
convert_to_json

Break up the types Column

To break up the types column, you can use explode(column='types') which breaks up the list and creates a new row for each list item.

expand_types = convert_to_json.explode(column='types')
expand_types

Drop Duplicates

Next, you’ll notice that the types column has a few duplicates like political and locality. We can remove them using drop_duplicates().

drop_duplicates = expand_types.drop_duplicates(subset=['types'])
drop_duplicates

Set Index and Isolate the Long Name

Finally, we can set the index as our types column and isolate the long_name column to return a series.

set_index_and_isolate_long_name = drop_duplicates.set_index('types')['long_name']
set_index_and_isolate_long_name

Writing a Pandas Function

Here is how you can make this into a Pandas function so that you can apply to a DataFrame.

def get_adress(x):
  '''
  Takes in latitude and longitude and returns and address using the Google API
  '''
  point = [x.latitude,x.longitude]
  address = geolocator.reverse(point,exactly_one=True)

  try:
    address = geolocator.reverse(point,exactly_one=True)
    return pd.json_normalize(address.raw['address_components']).explode(column='types').drop_duplicates(subset=['types']).set_index('types')['long_name']
  except:
    pass

Using Nominatim

Using the Google Maps API is very accurate and returns a lot of great information. The caveat is that you do have to pay for the service after a certain limit. A free way of doing a reverse address lookup is to use geopy with Nominatim. Here is an example of how you would do a reverse address lookup using it.

First let’s import the packages:

from geopy.geocoders import Nominatim
from geopy.extra.rate_limiter import RateLimiter
import pandas as pd

locator = Nominatim(user_agent="myGeocoder")

Next, we will create a function that takes a DataFrame as the argument.

def get_adress(x):
  '''
  Takes in latitude and longitude and returns and address using the Google API
  '''
  coordinates = [x.latitude,x.longitude]
  location = locator.reverse(coordinates)
  address = location.raw
  address_converted = pd.json_normalize(address).squeeze() #squeeze converts a dataframe to a pandas series

  return address_converted

Now we can apply the function to the test DataFrame we made at the beginning of the post:

df.apply(get_adress ,axis=1)

Lastly, you can merge this address data back to the original DataFrame by running pd.concat([df,addresses_df], axis=1)

Final Thoughts

Check out more Python tricks in this Colab Notebook or in my recent Python Posts.

Thanks for reading!


Posted

in

by

Tags: