I have a model that requires a stupid number of conditional statements. The older version was utilizing feature layers, select by attributes, and Calculate fields many, many times. I rewrote it to utilize a mass of nested if, elif, and else statements as well as a dictionary made from a search cursor from another feature class.
My problem is that I'm not quite sure where to place updateRow(row) statements so that the data is properly updated. The cursor updates a lot of different fields. Most of them are simple updates, but almost all still depend on various conditional statements. This question is for a single simple segment before the messiest parts.
I tried to simplify it as much as possible to show. I assign the age field within the cursor but also need to reference that same field (after its been assigned) to perform calculations. Do I need to update the row after each age or would the cursor.updateRow(row) line be placed after the age assignment and then a gain after the AgeMult assignments?
with arcpy.da.UpdateCursor(ci_masterpoints, flds) as cursor:
# start looking at rows
for row in cursor:
row[flds.index('TodaysDate')] = datetime.datetime.now().strftime('%d/%m/%Y')
row[flds.index('TodaysDateYr')] = datetime.datetime.now().year
age = row[flds.index('Age')]
# If the work order number matches to a wonum in conditions...
if mx_row in conditions:
row[flds.index('Leak_Location')] = conditions[mx_row]
# Avoid null values but assign year based on Actual_Finish
if row[flds.index('Actual_Finish')] != None:
# Assign the year to DateInstallYr
row[flds.index('DateInstallYr')] = row[flds.index('Actual_Finish')].year
age = row[flds.index('TodaysDateYr')] - row[flds.index('DateInstallYr')]
if age == None:
row[flds.index('AgeMult')] = 1
elif age > 10 and age < 20:
row[flds.index('AgeMult')] = 0.9
elif age > 20:
row[flds.index('AgeMult')] = 0.75
-
Just a minor point: What should happen if age is exactly 20?Berend– Berend2022年02月03日 07:37:15 +00:00Commented Feb 3, 2022 at 7:37
-
No idea! I don't really understand 90% of what's in this model or the reasoning for it. Like why do we have a field with the days date instead of just calculating things with variables?JackOfTales– JackOfTales2022年02月03日 12:28:20 +00:00Commented Feb 3, 2022 at 12:28
1 Answer 1
Run your cursor.updateRow(row)
just once per row that includes any changes and run it after all changes for that row. Since you change values for every row (at least for the dates), then you need to run it once for each row, after all changes for the row.
Therefore run it as the last line in the for
loop, outside of any if
clauses. Ie, Use only one cursor.updateRow(row)
statement.
The cursor.updateRow(row)
writes all values for that row at once, so there's no point running it for each value. Run it once only for the entire row.
Eg:
with arcpy.da.UpdateCursor(ci_masterpoints, flds) as cursor:
# start looking at rows
for row in cursor:
row[flds.index('TodaysDate')] = datetime.datetime.now().strftime('%d/%m/%Y')
row[flds.index('TodaysDateYr')] = datetime.datetime.now().year
age = row[flds.index('Age')]
# If the work order number matches to a wonum in conditions...
if mx_row in conditions:
row[flds.index('Leak_Location')] = conditions[mx_row]
# Avoid null values but assign year based on Actual_Finish
if row[flds.index('Actual_Finish')] != None:
# Assign the year to DateInstallYr
row[flds.index('DateInstallYr')] = row[flds.index('Actual_Finish')].year
age = row[flds.index('TodaysDateYr')] - row[flds.index('DateInstallYr')]
if age == None:
row[flds.index('AgeMult')] = 1
elif age > 10 and age < 20:
row[flds.index('AgeMult')] = 0.9
elif age > 20:
row[flds.index('AgeMult')] = 0.75
cursor.updateRow(row)