1

I've looked everywhere online trying to find a solution but I can't find one anywhere. I'm reading an address from a CSV file and geocoding and writing two new columns into a new CSV. This works with small sample sizes I've chosen, but it appears my API can't get the longitude and latitude values for some addresses thus causing an error. Here's my code:

import geopy
import pandas 
from geopy.geocoders import Bing


def main():
    io = pandas.read_csv('newoutput3.csv',index_col=None, header=0, 
    sep=",",encoding='cp1252')
    def get_latitude(x):
      if x.latitude is None:
         x.latitude = None
      else:
         return x.latitude


    def get_longitude(x):
      if x.longitude is None:
         x.longitude = None
      else:
         return x.longitude

    geolocator = Bing('myAPIkey',timeout=5)
    geolocate_column = io['ADDRESS'].apply(geolocator.geocode)
    io['latitude'] = geolocate_column.apply(get_latitude)
    io['longitude'] = geolocate_column.apply(get_longitude)
    io.to_csv('geocoding-output17.csv')   




if __name__ == '__main__':
    main()

File "C:/Users/Chris/Downloads/WPy-3662/scripts/geocoder.py", line 16, in 
get_latitude
   if x.latitude is None:

AttributeError: 'NoneType' object has no attribute 'latitude'

I still want the script to do what it does even if it can't get the latitude or longitude for certain addresses, how do i go about ignoring it?

4
  • What is the question? How to not get that error? In that case, you might want to check if x is None and not x.latitude x.longitude is None. Hope it helps. Commented Nov 5, 2018 at 23:51
  • Please edit your post to include a copy of the full Traceback of your error! Commented Nov 5, 2018 at 23:51
  • Yes I just want to know how to ignore the error and still carry on with the script, and did I not check if x is none? Thats what I did in the two functiosn I thought. @datapug Commented Nov 5, 2018 at 23:58
  • @seatal in the code you check is x.latitude is None but not if x is None, they are two different things. Try to replace x.latitude is None with x is None and x.longitude is None with x is None Commented Nov 6, 2018 at 0:42

4 Answers 4

3

There is a difference between an attribute having "None" as a value and the attribute not existing at all. This is analogous to an undefined variable: the code below fails when my_variable is not defined instead of returning False:

>>> my_variable == None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'my_variable' is not defined 

To check if an object has an attribute of name longitude you can use:

# Returns True/False depending on whether x.longitude is an existing attribute
>>> hasattr(x, 'longitude')
False

In order to see this behavior in your code you could change the functions get_longitude/get_latitude like so:

def get_latitude(x):
  if hasattr(x,'latitude') and (x.latitude is not None): 
     return x.latitude


def get_longitude(x):
  if hasattr(x,'longitude') and (x.longitude is not None): 
     return x.longitude
Sign up to request clarification or add additional context in comments.

2 Comments

okay thank you, how would I go about implementing this if I still want the script to continue even if for some addresses it can't get the longitude or latitude?
I just updated my answer to include the way that I would personally modify that code
3

The problem here is that you are tring to get 'latitude' and 'longitude' from a None object. Basically doing None.latitude. So the best way to go about this is to first check if the geocoder returns a value before you try to access the 'longitude' and 'latitude'.

lat = []
long = []
for row in io['ADDRESS']:
    addr = geolocator.geocode(row, timeout=10)
    if addr is None:
        lat.append(None)
        long.append(None)
    else:
        latitude = ad.latitude
        longitude = ad.longitude  
    
    lat.append(latitude)
    long.append(longitude)

io['latitude'] = lat
io['longitude'] = long



           

I faced the same issue you have and this was how I was able to resolve it

3 Comments

#sammyhawkrad can you explain how can i change the script to not get this error: "Length of values (52) does not match length of index (40)"
@RitaM I am a little lost. It seems to me you are getting the error from the additional code you have and not from the script I've shared here. You could share your complete code so I can see if I can help.
i solved the problem. I wasn`t your script. Sory :)
1

jfbeltran is right about the difference between None for the value and non-existing attribute for an object instance. geopy's geocode methods return None for locations which haven't been found.

Here is, IMO, a nicer way to solve you problem which doesn't require defining own functions:

import operator

non_null_geolocate_column = geolocate_column[~geolocate_column.isnull()]
io['latitude'] = None
io['latitude'] = non_null_geolocate_column.apply(operator.attrgetter('latitude'))
io['longitude'] = None
io['longitude'] = non_null_geolocate_column.apply(operator.attrgetter('longitude'))

For geopy specifically, you may find the Usage with pandas documentation section helpful: https://geopy.readthedocs.io/en/stable/#usage-with-pandas

Comments

0

To get coordinates from a column with address this also works just fine:

df.column.apply
(
lambda x: geolocator.geocode(x).latitude if geolocator.geocode(x) != None else 'NF'
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.