I wanted to get the latitude and longitude of an adress with geopy. My code is
geolocator = Nominatim(user_agent="EXAMPLE")
location = geolocator.geocode("Wismarsche Straße 393-397 19049 Schwerin")
lat = str(location.latitude)
lon = str(location.longitude)
latLon = str(lat) + ";" + str(lon) + ";"
and it outputs NoneType.
Does anyone know why?
The documentation states that the geocode method returns None when no results are found. In your case, removing 19049 from your query returns a result:
location = geolocator.geocode("Wismarsche Straße 393-397 Schwerin")
lat = str(location.latitude)
lon = str(location.longitude)
latLon = str(lat) + ";" + str(lon) + ";"
print(f'Latitude: {lat}, longitude: {lon}, latLon: {latLon}')
Ouput:
Latitude: 53.6519479, longitude: 11.4073671, latLon: 53.6519479;11.4073671;
Related
I'm looping through records in a dataframe column and trying to pull geocode data for each. Here's the code that I'm testing.
from geopy.geocoders import Nominatim
geolocator = Nominatim(user_agent="http")
for item in df_fin['market_address']:
try:
location = geolocator.geocode(item)
df_fin.loc['address'] = location.address
df_fin.loc['latitude'] = location.latitude
df_fin.loc['longitude'] = location.longitude
df_fin.loc['raw'] = location.raw
print(location.raw)
except:
df_fin.loc['raw'] = 'no info for: ' + item
print('no info for: ' + item)
I must be missing something simple, but I'm just not seeing what the issue is here.
UPDATE:
from geopy.geocoders import Nominatim
geolocator = Nominatim(user_agent="http")
for index, row in df_fin.market_address.iterrows():
try:
location = geolocator.geocode(row)
row['address'] = location.address
row['latitude'] = location.latitude
row['longitude'] = location.longitude
row['raw'] = location.raw
print(location.raw)
except:
row['raw'] = 'no info for: ' + row
print('no info for: ' + row)
df_fin.tail(10)
You can reference below code :
from geopy.geocoders import Nominatim
geolocator = Nominatim(user_agent="http")
for index, row in df_fin.iterrows():
try:
location = geolocator.geocode(item)
row['address'] = location.address
row['latitude'] = location.latitude
row['longitude'] = location.longitude
row['raw'] = location.raw
print(location.raw)
except:
row['raw'] = 'no info for: ' + item
print('no info for: ' + item)
And if you are more familiar with Pandas, you can use #DYZ's answer.
You should define a function that converts market_address into the address, lat, and long, and .apply that function to the DataFrame.
def locate(market_address):
loc = geolocator.geocode(market_address)
return pd.Series({'address': loc.address if loc else np.nan,
'latitude': loc.latitude if loc else np.nan,
'longitude': loc.longitude if loc else np.nan,
'raw': loc.raw if loc else np.nan})
df_fin.join(df_fin['market_address'].apply(locate))
Note that loc.raw is a dictionary. When you store a dictionary in a DataFrame, you are looking for trouble in the future.
So I'm making this Weather app since API for weather data takes only latitude and longitude (afaik) I'm using another API to get them by city name. So GetGeo takes city name and returns latitude and longitude which then I need to use in GetWeather function the problem is I don't know how to make them accessible in this function, the only way I found is lat, lon = GetGeo() but this isn't working since GetGeo is taking argument which I pass in from input field. I understand that this probably isn't the best way to do this but I'm a beginner and I already made this work without having separate functions, but I like to challenge myself and want to separate everything in functions :)
def GetGeo(cityName):
locationKey = 'xxx'
locationUrl = "https://eu1.locationiq.com/v1/search.php?key=" + locationKey + '&q=' + cityName + '&format=json'
locationDataReq = requests.get(locationUrl)
locationData = locationDataReq.json()
lat = locationData[0]['lat']
lon = locationData[0]['lon']
return lat, lon
def GetWeather():
lat, lon = GetGeo()
darkSkyKey = 'xxx'
darkSkyUrl = "https://api.darksky.net/forecast/" + darkSkyKey + "/" + lat + "," + lon + "?units=si"
darkSkyDataReq = requests.get(darkSkyUrl)
darkSkyData = darkSkyDataReq.json()
label["text"] = darkSkyData
print(darkSkyData)
How about:
def GetGeo(cityName):
locationKey = 'xxx'
locationUrl = "https://eu1.locationiq.com/v1/search.php?key=" + locationKey + '&q=' + cityName + '&format=json'
locationDataReq = requests.get(locationUrl)
locationData = locationDataReq.json()
lat = locationData[0]['lat']
lon = locationData[0]['lon']
return lat, lon
def GetWeather(cityName):
lat, lon = GetGeo(cityName)
darkSkyKey = 'xxx'
darkSkyUrl = "https://api.darksky.net/forecast/" + darkSkyKey + "/" + lat + "," + lon + "?units=si"
darkSkyDataReq = requests.get(darkSkyUrl)
darkSkyData = darkSkyDataReq.json()
label["text"] = darkSkyData
print(darkSkyData)
qCity=input('please type city: ')
GetWeather(qCity)
I can search a shapefile for an attribute and it works fine but I don't know how to get the other fields in that record once the correct records is found. Don't know if I should use SearchCursor or SelectLayerByAttribute_management.
townlands = r'F:\MyProject\Assignment\townlands.shp'
outpath = r'F:\MyProject\Assignment'
the_townland=str(text_search_townland.get())
selection = str(""" "NAME_TAG" = '""" + the_townland + "'")
selection2 = ????????????????
print selection, selection2
This code is working in that it finds the townland that the user puts in text_search_townland and it prints it as selection. I'm looking to get another field called OSM_USER from that record into selection2.
I got this working after lots of trial and error. It does need SearchCursor or at least that is how I got it working.
def new_record():
#set environment variables.
arcpy.env.workspace = r'F:\MyProject\Assignment\folklore.gdb'
myPath = r'F:\MyProject\Assignment\folklore.gdb'
editRows = arcpy.da.InsertCursor('folklore', '*')
print editRows.fields
# get the centroid of the townland from townland_centroid (fc) based on the
# townland the user enters.
database = r'F:\MyProject\Assignment\folklore.gdb'
fc = database + '/' + 'townland_centroid'
the_townland=str(text_search_townland.get())
fields = ['NAME_TAG', 'X_coord', 'Y_coord']
whereClause = '"NAME_TAG"' + " = '" + the_townland + "'"
with arcpy.da.SearchCursor(fc, fields, whereClause) as cursor:
for row in cursor:
print('{0}, {1}, {2}'.format(row[0], row[1], row[2]))
X_coord = str(row[1])
Y_coord = str(row[2])
del cursor
# Set variables with values that will populate 'folklore' featureclass.
OID = 1
ptShape = arcpy.Point(0,0)
townland = text_search_townland.get()
county = var_county2.get()
category = var_category.get()
URL = text_search_URL.get()
spec_location = "text_search_speclocation.get()"
date_entered = text_search_date_entered.get()
story_year = int(text_search_story_year.get())
X_coord_put = X_coord
Y_coord_put = Y_coord
newRecord = [OID, ptShape, townland, county, URL, spec_location, date_entered, story_year, category, X_coord, Y_coord]
editRows.insertRow(newRecord)
del editRows
Hope this helps someone.
I am trying to parse a string as below using PyParsing.
R1# show ip bgp
BGP table version is 2, local router ID is 1.1.1.1
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete
Network Next Hop Metric LocPrf Weight Path
> 10.1.1.0/24 192.168.1.2 0 0 200 i
Note that LocPrf value is empty but it can be a number.
ipField = Word(nums, max=3)
ipAddr = Combine(ipField + "." + ipField + "." + ipField + "." + ipField)
status_code = Combine(Optional(oneOf("s d h * r")) + ">" + Optional(Literal("i"))
prefix = Combine(ipAddr + Optional(Literal("/") + Word(nums,max=2)))
next_hop = ipAddr
med = Word(nums)
local_pref = Word(nums) | White()
path = Group(OneOrMore(Word(nums)))
origin = oneOf("i e ?")
This is the grammar.
g = status_code + prefix + next_hop + med + local_pref + Suppress(Word(nums)) + Optional(path) + origin
I just need to parse the Bold line. But this is not parsing it properly. It assigns Weight value to LocPrf.
Please look over the following code example (which I will include in the next pyparsing release). You should be able to adapt it to your application:
from pyparsing import col,Word,Optional,alphas,nums,ParseException
table = """\
12345678901234567890
COLOR S M L
RED 10 2 2
BLUE 5 10
GREEN 3 5
PURPLE 8"""
# function to create column-specific parse actions
def mustMatchCols(startloc,endloc):
def pa(s,l,t):
if not startloc <= col(l,s) <= endloc:
raise ParseException(s,l,"text not in expected columns")
return pa
# helper to define values in a space-delimited table
def tableValue(expr, colstart, colend):
return Optional(expr.copy().addParseAction(mustMatchCols(colstart,colend)))
# define the grammar for this simple table
colorname = Word(alphas)
integer = Word(nums).setParseAction(lambda t: int(t[0])).setName("integer")
row = (colorname("name") +
tableValue(integer, 11, 12)("S") +
tableValue(integer, 15, 16)("M") +
tableValue(integer, 19, 20)("L"))
# parse the sample text - skip over the header and counter lines
for line in table.splitlines()[2:]:
print
print line
print row.parseString(line).dump()
I am geotagging JPEGs using the pyexiv2 Python module using code I found in another SO answer (see: What is the best way to geotag jpeg-images using Python?) and I have a question about the GPSTag value.
The code given in the answer has the following lines:
exiv_image["Exif.Image.GPSTag"] = 654
exiv_image["Exif.GPSInfo.GPSMapDatum"] = "WGS-84"
exiv_image["Exif.GPSInfo.GPSVersionID"] = '2 0 0 0'
I have looked at the Exiv2 documentation and found descriptions of GPSTag, GPSMapDatum, and GPSVersionID but am still confused about the value for GPSTag.
From the documentation it says:
A pointer to the GPS Info IFD. The Interoperability structure of the GPS Info IFD, like that of Exif IFD, has no image data.
This description does not really explain how to determine what value to use and I have not been able to find a better description of GPSTag online.
So my questions are:
Given a new image, how do you determine the value of Exif.Image.GPSTag?
Why is the code sample using a value of 654 (this may be answered by question one)?
Thanks for your help.
Best way to geotag photos using pyexiv2 is definitely with my program, GottenGeography ;-)
But seriously though, if you're wanting to access GPS data from pyexiv2, that code looks like this:
GPS = 'Exif.GPSInfo.GPS'
try:
self.latitude = dms_to_decimal(
*self.exif[GPS + 'Latitude'].value +
[self.exif[GPS + 'LatitudeRef'].value]
)
self.longitude = dms_to_decimal(
*self.exif[GPS + 'Longitude'].value +
[self.exif[GPS + 'LongitudeRef'].value]
)
except KeyError:
pass
try:
self.altitude = float(self.exif[GPS + 'Altitude'].value)
if int(self.exif[GPS + 'AltitudeRef'].value) > 0:
self.altitude *= -1
except KeyError:
pass
And writing looks like this:
self.exif[GPS + 'AltitudeRef'] = '0' if self.altitude >= 0 else '1'
self.exif[GPS + 'Altitude'] = Fraction(self.altitude)
self.exif[GPS + 'Latitude'] = decimal_to_dms(self.latitude)
self.exif[GPS + 'LatitudeRef'] = 'N' if self.latitude >= 0 else 'S'
self.exif[GPS + 'Longitude'] = decimal_to_dms(self.longitude)
self.exif[GPS + 'LongitudeRef'] = 'E' if self.longitude >= 0 else 'W'
self.exif[GPS + 'MapDatum'] = 'WGS-84'
With these support functions:
class Fraction(fractions.Fraction):
"""Only create Fractions from floats.
>>> Fraction(0.3)
Fraction(3, 10)
>>> Fraction(1.1)
Fraction(11, 10)
"""
def __new__(cls, value, ignore=None):
"""Should be compatible with Python 2.6, though untested."""
return fractions.Fraction.from_float(value).limit_denominator(99999)
def dms_to_decimal(degrees, minutes, seconds, sign=' '):
"""Convert degrees, minutes, seconds into decimal degrees.
>>> dms_to_decimal(10, 10, 10)
10.169444444444444
>>> dms_to_decimal(8, 9, 10, 'S')
-8.152777777777779
"""
return (-1 if sign[0] in 'SWsw' else 1) * (
float(degrees) +
float(minutes) / 60 +
float(seconds) / 3600
)
def decimal_to_dms(decimal):
"""Convert decimal degrees into degrees, minutes, seconds.
>>> decimal_to_dms(50.445891)
[Fraction(50, 1), Fraction(26, 1), Fraction(113019, 2500)]
>>> decimal_to_dms(-125.976893)
[Fraction(125, 1), Fraction(58, 1), Fraction(92037, 2500)]
"""
remainder, degrees = math.modf(abs(decimal))
remainder, minutes = math.modf(remainder * 60)
return [Fraction(n) for n in (degrees, minutes, remainder * 60)]
Although I am currently working on an alternative to pyexiv2 that uses GObject introspection to access the exiv2 library much more directly, called GExiv2, and would love to have some feedback on it. Both gexiv2 and pyexiv2 are wrappers around the same exiv2 library, but the difference is that pyexiv2 is a very large project with lots of glue, only works in python, and is on the brink of abandonment*; whereas gexiv2 is light and nimble, accessible from any programming language, and is well maintained thanks to it's use by Shotwell.
Hope this helps!
* pyexiv2's author, Olivier Tilloy, has asked me for help with maintainership as he no longer has much time
My version, a little lengthy...
from fractions import Fraction
import pyexiv2
try:
metadata = pyexiv2.metadata.ImageMetadata(image_file)
metadata.read();
thumb = metadata.exif_thumbnail
try:
latitude = metadata.__getitem__("Exif.GPSInfo.GPSLatitude")
latitudeRef = metadata.__getitem__("Exif.GPSInfo.GPSLatitudeRef")
longitude = metadata.__getitem__("Exif.GPSInfo.GPSLongitude")
longitudeRef = metadata.__getitem__("Exif.GPSInfo.GPSLongitudeRef")
latitude = str(latitude).split("=")[1][1:-1].split(" ");
latitude = map(lambda f: str(float(Fraction(f))), latitude)
latitude = latitude[0] + u"\u00b0" + latitude[1] + "'" + latitude[2] + '"' + " " + str(latitudeRef).split("=")[1][1:-1]
longitude = str(longitude).split("=")[1][1:-1].split(" ");
longitude = map(lambda f: str(float(Fraction(f))), longitude)
longitude = longitude[0] + u"\u00b0" + longitude[1] + "'" + longitude[2] + '"' + " " + str(longitudeRef).split("=")[1][1:-1]
latitude_value = dms_to_decimal(*metadata.__getitem__("Exif.GPSInfo.GPSLatitude").value + [metadata.__getitem__("Exif.GPSInfo.GPSLatitudeRef").value]);
longitude_value = dms_to_decimal(*metadata.__getitem__("Exif.GPSInfo.GPSLongitude").value + [metadata.__getitem__("Exif.GPSInfo.GPSLongitudeRef").value]);
print "--- GPS ---"
print "Coordinates: " + latitude + ", " + longitude
print "Coordinates: " + str(latitude_value) + ", " + str(longitude_value)
print "--- GPS ---"
except Exception, e:
print "No GPS Information!"
#print e
# Check for thumbnail
if(thumb.data == ""):
print "No thumbnail!"
except Exception, e:
print "Error processing image..."
print e;