1

I am struggling a bit with debugging my code, over something that seems very simple. I am using an update cursor to copy and convert existing string data into a new float column of my shapefile's attribute data. In the original column titled "DIRECTION_" consists of strings with the following values: n, e, s, w, ne, nw, se, sw; 0-360; and finally, just blank entries. See the figure below.

Original column in attribute data, when right clicking on column ArcMAP says type is a string

Here is a picture of my code, with a typo in the comment. (TYPO = "short integer field", when should be "float type"). This code results in all other values inputted as zero except of NSEW.

enter image description here

I have tried to change the type of the new field to FLOAT, LONG, SHORT. And I have tried the following else statements at the end of my for loop, all resulting in type errors.

else:
    row[1] == float(row[0]) #gives Value error: could not convert string to float
else:
    row[1] == row(0)
else:
    row[1] == int(row[0]) #gives error: The value type is incompatible with the field type
else:
    row[1] = row[0] #gives RuntimeError: The value type is incompatible with the field type
2
  • 1
    Welcome to GIS SE! Please use the edit button beneath your question to include that code as text in preference to as a picture so that it can be both searched and copy/pasted for testing.
    – PolyGeo
    Mar 5, 2016 at 19:59
  • 1
    Using multiple ifs can be confusing at least, replacing them by 2 lists or even better by dictionary, e.g. gis.stackexchange.com/questions/177479/… will make your code work faster and easier to debug. Hyperlink points to near identical question
    – FelixIP
    Mar 6, 2016 at 3:46

1 Answer 1

3

In your code snippet above you have a double equals == rather than single in your else

else:
    row[1] == row[0] #if entry has a number, copy that number into the new DIR_int column

This won't work. You need to use

else:
    row[1] = row[0] #if entry has a number, copy that number into the new DIR_int column

But probably what is breaking your code is that you're not checking for empty values (or values with spaces) rather than Null values. The following code snippet should work. It checks that there is a value in the cell, and if it is that it isn't a space. Any spaces, empty cells, or Nulls are transferred into the new column as a Null value.

cursor = da.UpdateCursor(points, ["DIRECTION_", "DIR_int"])

for row in cursor:
    if not row[0] == None and len(row[0]) > 0: # Check if row[0] has a value
        rowValue = row[0].strip() # Strips any leading/trailing spaces
        if rowValue == 'n':
            row[1] = 0
        elif rowValue == 'e':
            row[1] = 90
        elif rowValue == 's':
            row[1] = 180
        elif rowValue == 'w':
            row[1] = 270
        elif rowValue == 'ne':
            row[1] = 45
        elif rowValue == 'nw':
            row[1] = 315
        elif rowValue == 'se':
            row[1] = 135
        elif rowValue == 'sw':
            row[1] = 225
        elif rowValue.isnumeric(): # Checks if the value is a number
            row[1] = rowValue
        else: # If it still doesn't work, make it a Null
            row[1] = None
    else: # If row[0] doesn't have a value, then set row[1] to Null
        row[1] = None
    cursor.updateRow(row)

Here is a screenshot of my output - I've used your values (as far as I can tell regarding empty values) plus added a few more to test.

enter image description here

EDIT:

Working on FelixIP's suggestion above about using a Dictionary, the following looks a lot easier to read (and edit):

cursor = da.UpdateCursor(points, ["DIRECTION_", "DIR_int"])

def directions(value):
    dirDict = { 
                'n': 0, 
                'e': 90, 
                's': 180, 
                'w': 270, 
                'ne': 45, 
                'nw': 315, 
                'se': 135, 
                'sw': 225 
              }
    return dirDict.get(value, None)

for row in cursor:

    if row[0] and len(row[0]) > 0: # Check if row[0] has a value
        rowValue = row[0].strip().lower() # Strips any leading/trailing spaces

        if rowValue.isnumeric(): # If it's numeric, just use the existing value
            row[1] = rowValue
        else: # If it's not numeric, then look it up in the dictionary
            row[1] = directions(rowValue)

    else: # If row[0] doesn't have a value, then set row[1] to Null
        row[1] = None

    cursor.updateRow(row)
8
  • I just spotted the issue. You don't have Nulls, you have some kind of value (perhaps ' ' - a space)
    – Midavalo
    Mar 5, 2016 at 21:20
  • Updated to check for empty/space values
    – Midavalo
    Mar 5, 2016 at 21:38
  • Updated again to include code snippet with dictionary
    – Midavalo
    Mar 6, 2016 at 23:48
  • Hi friends, off of Midavalo's answer I got the following error:Traceback (most recent call last): File "C:/Users/jenboyer/Desktop/Spatial Spread W.Hyacinth/182 project/buffscript_3.8.py", line 92, in <module> cursor.updateRow(row) RuntimeError: The field is not nullable. [DIR_int]
    – Jebo
    Mar 8, 2016 at 22:14
  • Problem resolved: changed return dirDict.get(value, None) to --> return dirDict.get(value, 0) and it worked just fine. Thank you thank you!
    – Jebo
    Mar 8, 2016 at 22:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.