da.UpDateCursor to conditionally calculate a field based on test of another field

1003
7
Jump to solution
05-23-2014 03:22 PM
PaulHuffman
Occasional Contributor III
I was testing out arcpy.da.UpdateCursor to calculate a field based on another fields value.  My script runs without error, but doesn't seem to make any changes in the shapefile.  I tried adding the line overwriteOutput = "True" but that didn't work.  The print line I added for debugging shows the correct values for ReddStatus or row[1], but they don't get saved in the output.

 # Import arcpy module import arcpy from arcpy import env env.workspace = "C:\\avdata\\PythonTest\\" arcpy.env.overwriteOutput = "True"  # Local variables: inshape = "zilltogra101013.shp" #input shapefile field1 = "PassNum" #field with test values field2 = "ReddStatus" #field to be calculated fields = ['PassNum', 'ReddStatus']       with arcpy.da.UpdateCursor(inshape, fields) as cursor:     for row in cursor:                  if row[0] == 1:            row[1] = "Definite"         elif row[0] == 2:            row[1] = "Probable"         print row[0],row[1], '\n'
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
curtvprice
MVP Esteemed Contributor
The "cursor.field" syntax doesn't work with variables, just field names. Here's how you get the values if the field is a variable. And, as was mentioned - don't forget the updateRow again -- you need that to write the data to the table.
rows = arcpy.UpdateCursor(inshape)         for row in rows:     if row.getValue(field1) == 1:        row.setValue(field2, "Definite")     elif row.getValue(field1) == 2:        row.setValue(field2, "Probable")     rows.updateRow(row)

View solution in original post

0 Kudos
7 Replies
PaulHuffman
Occasional Contributor III
Apparently I just need to add a line cursor.updateRow(row) at the end of the loop to write the changes. (As shown in the documentation, if I would ever just read farther along. )

But another problem showed up.  I was trying to show a colleague how to do this, but he only has ArcGIS 10.0, so he doesn't have da.UpdateCursor.  I need to come up with a way using just arcpy.UpdateCursor.  I've tried a couple different loops but come up with either the input file doesn't exist or the field field1 doesn't exist.
# Import arcpy module
import arcpy
from arcpy import env
env.workspace = "C:\\avdata\\PythonTest\\testgdb.gbd\\"

# Local variables:
fc = "zilltogra" #input Feature class
field1 = "PassNum" #field with test values
field2 = "ReddStatus" #field to be calculated

items = arcpy.ListFields(fc)
print items
##cursor = arcpy.UpdateCursor(inshape)
##row = cursor.next()
##while row:
##    if row.field1 == 1:
##        row.field2 = "Definite"
##    elif row.field1 == 2:
##        row.field2 = "Probable"
##    cursor.updaterow(row)
##    row = cursor.next(1)
    
rows = arcpy.UpdateCursor(fc)    
for row in rows:
    if row.field1 == 1:
       row.field2 = "Definite"
    elif row.field1 == 2:
       row.field2 = "Probable"


# Import arcpy module
import arcpy
from arcpy import env
env.workspace = "C:\\avdata\\PythonTest\\"

# Local variables:
inshape = "zilltogra101013.shp" #input shapefile
field1 = "PassNum" #field with test values
field2 = "ReddStatus" #field to be calculated
fields = ['PassNum', 'ReddStatus'] 

##cursor = arcpy.da.UpdateCursor(inshape)
##row = cursor.next()
##while row:
##    if row.field1 == 1:
##        row.field2 = "Definite"
##    elif row.field1 == 2:
##        row.field2 = "Probable"
##    cursor.updaterow(row)
##    row = cursor.next(1)
    
rows = arcpy.UpdateCursor(inshape)        
for row in rows:
    if row.field1 == 1:
       row.field2 = "Definite"
    elif row.field1 == 2:
       row.field2 = "Probable"
0 Kudos
Zeke
by
Regular Contributor III
You still have to actually update the row. Sounds like the same issue as your first post, based on the code you posted.

edit: I think the main problem may be where you assign the field names to the variables field1 and field2. Arcpy doesn't like this with the . notation. It looks for an actual field named field1, which doesn't exist. Technically, it's looking for a property of the row class with the value field1, when the value is PassNum. Try row.PassNum and row.ReddStatus.

edit redux: note that this would be incorrect when using da, which returns an index based tuple and is referenced by index number.
0 Kudos
curtvprice
MVP Esteemed Contributor
The "cursor.field" syntax doesn't work with variables, just field names. Here's how you get the values if the field is a variable. And, as was mentioned - don't forget the updateRow again -- you need that to write the data to the table.
rows = arcpy.UpdateCursor(inshape)         for row in rows:     if row.getValue(field1) == 1:        row.setValue(field2, "Definite")     elif row.getValue(field1) == 2:        row.setValue(field2, "Probable")     rows.updateRow(row)
0 Kudos
PaulHuffman
Occasional Contributor III
Thanks guys.  All I needed to add was

del row
del rows


to release the locks on the attribute table.
0 Kudos
PaulHuffman
Occasional Contributor III
What's wrong with this approach,  using Field Calculator with a simple python function, no cursors?  Works well on my small test set. 

[ATTACH=CONFIG]34118[/ATTACH]
0 Kudos
T__WayneWhitley
Frequent Contributor
Well, sure, spoil all the fun and use the field calculator!
Yeah, that looks fine...but look at it this way:  now you have learned another option (probably a faster option) to use da cursor, and you don't need to open ArcMap, open the table, get to the field calculator, etc etc in order to execute a script.  In a script you can also, when needed, insert messaging and such on more complex operations to monitor or even trap where things go wrong on certain records.  When the field calculator fails, everything comes to a screeching halt.
0 Kudos
PaulHuffman
Occasional Contributor III
The guy I was helping with this told me that he had tried using the field calculator, but was overwhelmed by its complexity, so I steered away from the field calculator too.   Now he has two ways to do this.

Using da.cursor without opening ArcMap will be nice with large data sets,  but I couldn't notice the difference with my little test data set.   The longest part seemed to taken just loading arcpy.

My workflows often involve having ArcMap open so I can view and edit feature classes as I run through them. But that doesn't mean I can't drag some da.cursor code into the ArcMap python window for this kind of calculation.
0 Kudos