3

I am fairly new to Python, and am working with the SmartyStreets API. I am trying to read in a data frame that contains addresses and simply validate them. However, I am running into issues and not producing any results. The below code should simply output the print statements at the end for each of the rows in the data frame.

I would like the function to get the names of its variables from the columns in the data frame that contains the proper information.

For example: When reading in the data, the function should get its address variable from the Street1 column. Likewise, City, should come from City column, State from state and Zipcode from zipcode.

So for the first iteration, the function should store the variables as follows:

lookup.street = '1600 Amphitheatre Pkwy'
lookup.city = 'Mountain view"
lookup.state = 'CA'
lookup.zip = '94043'

The ultimate goal will be to get this to append a county column to the end of each row with the proper county from the API. However, I am not able to get this to run without errors. Any assistance would be helpful. If needed, you can obtain a free API key for 250 calls per month from the SmartyStreets website. The code that I have included comes from the examples on github. This may not be the most efficient way to do this, if you have a more efficient way to code this, feel free to include that in your response. The code used and error found is shown below.

import pandas as pd
from smartystreets_python_sdk import StaticCredentials, exceptions, ClientBuilder
from smartystreets_python_sdk.us_street import Lookup as StreetLookup

##Defines Dictionary
dict = {'Street1': ["1600 Amphitheatre Pkwy", "1 Infinite Loop", "1 Rosedale"],
        'City': ['Mountain view', 'Cupertino', 'Baltimore'],
        'State': ['CA', 'CA', 'MD'],
        'Zipcode': ['94043', '95014', '21237']}
##Converts Dictionary to Data Frame
df = pd.DataFrame(dict)

##Defines Function
def run(address = '', city = '', state = '', zipcode = ''):
    
    auth_id = 'ID HERE'
    auth_token = 'TOKEN HERE'
    
    credentials = StaticCredentials(auth_id, auth_token)
    
    client = ClientBuilder(credentials).build_us_street_api_client()
    
        
    lookup = StreetLookup()
    #lookup.input_id = '' ##Optional ID from your system
    #lookup.addressee = addressee
    lookup.street = address
    ##lookup.street2 = address2
    #lookup.secondary = secondary ##STE, Apartment, etc.
    #lookup.urbanization = '' ##PR Addresses ONLY
    lookup.city = city
    lookup.state = state
    lookup.zipcode = zipcode
    lookup.candidates = 1
    lookup.match = 'Invalid'

    try:
        client.send_lookup(lookup)
    except exceptions.SmartyException as err:
        print(err)
        return

    result = lookup.result

    if not result:
        print("No candidates. This means the address is not valid.")
        return

    first_candidate = result[0]

    print("Address is valid. (There is at least one candidate)\n")
    print("ZIP Code: " + first_candidate.components.zipcode)
    print("County: " + first_candidate.metadata.county_name)

    for c, candidate in enumerate(lookup.result):
        print("- {}: {}, {}, {}".format(c, candidate.delivery_line_1, candidate.last_line, candidate.metadata.county_name))

##Runs function     
df.apply(run(address = 'Street1',  city = 'City', state = 'State', zipcode = 'Zipcode'))

When this runs, I get the following error:

TypeError: ("'NoneType' object is not callable", 'occurred at index Steet1')

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Sven
  • 301
  • 2
  • 18
  • Don't know this API too well, and your code looks okay. Can you provide the line number that this error occurs at? – cmxu Jan 08 '20 at 18:30
  • Looks like in line 321: File "C:\Users\Name\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\apply.py", line 321, in apply_series_generator results[i] = self.f(v) TypeError: ("'NoneType' object is not callable", 'occurred at index Steet1') If you remove the function requirements so that the function is defined as run(), and you hard code a single address. Call run() in the terminal, you will get output. So it is calling the API correctly. My task is to adjust the given code so that it works in my function for a data frame. – Sven Jan 08 '20 at 18:40
  • Here is a link to the original code that I used to essentially build out my function: https://github.com/smartystreets/smartystreets-python-sdk/blob/master/examples/us_street_single_address_example.py – Sven Jan 08 '20 at 18:42
  • @Chris are you still getting the error now that you've fixed the typo? Is there a different error occurring now? – camiblanch Jan 08 '20 at 23:33

1 Answers1

1

As far as I can tell, there are a few issues. Firstly, you're dictionary calls the first column 'Steet1' but that should be 'Street1'. Secondly, I believe this is not the correct usage of apply. If you want to do something like this I suggest the following changes.

def run(row):
    address = row['Street1']
    city = row['City']
    state = row['State']
    zipcode = row['Zipcode']
    ...
df.apply(run, axis = 1)

Try that, let me know if that fixes things. Also, here since you are just printing things with the function run you could just loop over with a for loop and call the function, there is not necessarily a need to use apply, but that said it still should work.

cmxu
  • 954
  • 5
  • 13