[GIS] Python- use geocode function on table of addresses & copy lat/long to appropriate row

arcpygeocodinggeolocationpython

I have a table of addresses, and I need my Python script to use my Google API geolocate function to return lat/long coordinates for each and add to a new field in the same row for each address. The geocode function works fine- I just can't get the script to iterate through each row of the table, add the address to the function, and then copy the output lat/long to the field in the same row. here's what I have:

import urllib, json, time, arcpy

arcpy.env.workspace = "D:/GIS/addr.dbf"

#sets variables, adds new field to hold lat/long coordinates
fc = 'addr.dbf'
field1 = 'address'
field2 = 'loc'
arcpy.AddField_management(fc, field2, "TEXT")


#function that uses Google API to geolocate- this part works consistently
def geolocate(address, 
api="key_here",delay=4):
  base = r"https://maps.googleapis.com/maps/api/geocode/json?"
  addP = "address=" + address.replace(" ","+")
  gUrl = base + addP + "&key=" + api
  response = urllib.urlopen(gUrl)
  jres = response.read()
  jData = json.loads(jres)
  if jData['status'] == 'OK':
    resu = jData['results'][0]
    finList = [resu['formatted_address'],resu['geometry']['location'] 
    ['lat'],resu['geometry']['location']['lng']]
  else:
    finList = [None,None,None]
  time.sleep(delay)
  return finList


#adds address field as text to geolocate in function, adds output lat/long 
#(indexed locations 0 and 1 from the finList output)
##this is the part that doesn't work!
geo = geolocate(address = field1)
cursor = arcpy.UpdateCursor(fc, [field1, field2])
for row in cursor:
  field2 = geo[0], geo[1]
  cursor.updateRow(row);

Best Answer

first thing: download https://pypi.python.org/pypi/geocoder/1.8.0 this geocoder with pip install geocoder from your cmd.

now to simplify your code

import arcpy, geocoder

#sets variables, adds new field to hold lat/long coordinates
fc = r'dataset'
field1 = 'Address'
field2 = 'loc'
arcpy.AddField_management(fc, field2, "TEXT")

#function that uses Geocoder goolge maps API with simplicity
def geolocate(address):
    try:
        g=geocoder.google(address)
        x=g.latlng[1]
        y=g.latlng[0]
        coords="{} {}".format(x,y)
    except:
        coords="couldnt geocode"
    return coords
#use the da cursor they are more efficient
with arcpy.da.UpdateCursor(fc,(field1,field2)) as cursor:
    for row in cursor:
        row[1]=geolocate(row[0])
        cursor.updateRow(row)

in your original code geo = geolocate(address = field1) this line needed to be in the for loop to geocode row by row.

you can add various print statements along the way but this should work for you.

*if you do not want to use the geocoder library then just use your geolocate function instead of mine.

UPDATE

based on your comment to return the lat long values in their respective fields, I used a simple class

import arcpy, geocoder

#sets variables, adds new field to hold lat/long coordinates
fc = r'dataset'
field1 = 'Address'
latitude = 'Latitude'
longitude='Longitude'
arcpy.AddField_management(fc, latitude, "TEXT")
arcpy.AddField_management(fc, longitude, "TEXT")

#class that uses Geocoder goolge maps API
class geolocate:
    def __init__(self,address):
        self.address=address
        self.x=''
        self.y=''
    def latlongs(self):
        try:
            g=geocoder.google(self.address)
            self.x=str(g.latlng[1])
            self.y=str(g.latlng[0])
        except:
            self.x="could not geocode"
            self.y="could not geocode"
#use the da cursor they are more efficient
with arcpy.da.UpdateCursor(fc,(field1,latitude,longitude)) as cursor:
    for row in cursor:
        geo=geolocate(row[0])
        geo.latlongs()
        print geo.y +' '+geo.x
        row[1]=geo.y
        row[2]=geo.x
        cursor.updateRow(row)
Related Question