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?
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
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
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
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'
)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.