I have a dataframe with the longitude column and latitude column. When I try to get the address using geolocator.reverse()
I get the error ValueError: Must be a coordinate pair or Point
I can't for the life of me insert the lat and long into the reverse function without getting that error. I tried creating a tuple using list(zip(zips['Store_latitude'], zips['Store_longitude']))
but I get the same error.
Code:
import pandas as pd
from geopy.geocoders import Nominatim
from decimal import Decimal
from geopy.point import Point
zips = pd.read_excel("zips.xlsx")
geolocator = Nominatim(user_agent="geoapiExercises")
zips['Store_latitude']= zips['Store_latitude'].astype(str)
zips['Store_longitude'] = zips['Store_longitude'].astype(str)
zips['Location'] = list(zip(zips['Store_latitude'], zips['Store_longitude']))
zips['Address'] = geolocator.reverse(zips['Location'])
What my DataFrame looks like
Store_latitude | Store_longitude |
---|---|
34.2262225 | -118.4508349 |
34.017667 | -118.149135 |
CodePudding user response:
I think you might try with a tuple or a geopy.point.Point
before going to a list to see whether the package works all right.
I tested just now as follows (Python 3.9.13, command line style)
import geopy
p = geopy.point.Point(51.4,3.45)
gl = geopy.geocoders.Nominatim(user_agent="my_test") # Without the user_agent it raises a ConfigurationError.
gl.reverse(p)
output:
Location(Vlissingen, Zeeland, Nederland, (51.49433865, 3.415005767601362, 0.0))
This is as expected.
Maybe you should cast your dataframe['Store_latitude'] and dataframe['Store_longitude'] before/after you convert to list? They are not strings?
More information on your dataframe and content would be required to further assist, I think. Good luck!
EDIT: added information after OP's comments below.
- When you read your excel file as
zips = pd.read("yourexcel.xlsx")
you will get a pandas dataframe.
The content of the dataframe is two columns (which will be of type Series) and each element will be a numpy.float64 (if your excel has real values as input and not strings!). You can check this using the type() command:
>>> type(zips)
<class 'pandas.core.frame.DataFrame'>
>>> type(zips['Lat'])
<class 'pandas.core.series.Series'>
>>> type(zips['Lat'][0])
<class 'numpy.float64'>
What you then do is convert these floats (=decimal numbers) to a string (=text) by performing zips[...] = zips[...].astype(str)
. There is no reason to do that, because your geolocator requires numbers, not text.
- As shown in the comment by @Derek, you need to iterate over each row and while doing so, you can put the resulting Locations you receive from the geolocator in a new column.
So in the next block, I first create a new (empty) list. Then i iterate over couples of lat,lon by combining your zips['Lat'] and zips['lon'] using the zip command (so the naming of zips is a bit unlucky if you don't know the zip command; it thus may be confusing you). But don't worry, what it does is just combining the entries of each row in the varables lat and lon. Within the for-each loop, I append the result of the geolocator lookup. Note that the argument of the reverse command is a tuple (lat,lon), so the complete syntax is reverse( (lat,lon) ). Instead of (lat,lon), you could also have created a Point as in my original example. But that is not necessary imo. (note: for brevity I just write 'Lat' and 'Lon' instead of your Store...). Finally, assign the result list as a new column in your zip pandas dataframe.
import geopy as gp
# instiate a geolocator
gl = gp.geocoders.Nominatim(user_agent="my_test")
locations = [] # Create empty list
# For loop over each couple of lat, lon
for lat,lon in zip(zips['Lat'], zips['Lon']:
locations.append(gl.reverse((lat,lon))
# Add extra column to your pandas table (address will be the column name)
zips = zips.assign(address=locations)
One thing you still may want, is just have the text string instead of the complete geopy.Location() string in your table. To get that you write the for loop with this small modification ([0] as the first element of the Location object). Note that this won't work if the result of the lookup of a given row is empty (None). Then the [0] will raise an error.
# For loop over each couple of lat, lon
for lat,lon in zip(zips['Lat'], zips['Lon']:
locations.append(gl.reverse((lat,lon)[0])
I hope this gets you going!