Viral Mistry
Viral Mistry

Reputation: 73

Geopy reverse returns keyerrors for 'city', 'district' and 'borough' despite being in JSON response object

I'm trying to run a very simple geopy reverse script that takes a lat-long coordinate and returns specifically the country, state and city. All three of these are easily pulled from the JSON response object. However, when I try to extract the 'city' feature, I get a KeyError. If I double check to see if 'city' is in the response object, it definitely is (see below), so what exactly is going on? I can extract country and state without issue, why not the city? I've also noticed this happening for district and borough.

This is my code:

df = pd.read_csv('data.csv')
geolocator = Nominatim(user_agent='latlongconvert')
df['address'] = df['LastMatchingLatLong'].apply(geolocator.reverse)

df['country'] = df['address'].apply(lambda x: (x.raw['address']['country']))
df['state'] = df['address'].apply(lambda x: (x.raw['address']['state']))
df['city'] = df['address'].apply(lambda x: (x.raw['address']['city']))

Where the last line creates the following error: KeyError: 'city'

When I look at a particular row it clearly contains the city key:

df['address'][0].raw['address']

Ouput:
{'tourism': 'Schwanentempel',
 'road': 'Auedamm',
 'suburb': 'Südstadt',
 'city': 'Kassel',
 'municipality': 'Niestetal',
 'state': 'Hessen',
 'postcode': '34121',
 'country': 'Deutschland',
 'country_code': 'de'}

I can even use df['address'][0].raw['address']['city'] to extract it for that particular row.

Upvotes: 1

Views: 906

Answers (1)

Viral Mistry
Viral Mistry

Reputation: 73

For anyone else having this issue, Geopy does not always return city, borough, district, etc. so using a lambda function without accounting for missing values will give you a keyerror.

The following code sorted this issue out for me:

df['country'] = df['address'].apply(lambda x: (x.raw['address']['country']))
df['state'] = df['address'].apply(lambda x: (x.raw['address']['state']))
df['city'] = df['address'].apply(lambda x: (x.raw['address']['city'] if 'city' in x.raw['address'].keys() else None ))

Upvotes: 2

Related Questions