Hi all,
This feels like a problem that should have a really straightforward solution but for some reason I can't wrap my head around it. I have a simple arcade script that was given to me that was used in the Calculate Field window. I'm trying to take that expression and incorporate it into a python script in jupyter notebook.
This is the arcade script:
var LINED = $feature.LINED
var startDate = IIf(LINED == "Yes", Date($feature.LINEDYEAR), Date($feature.INSTALLDATE));
var endDate = Now();
var age = round(DateDiff(endDate, startDate, 'years'),2);
return age;
It's being used to populate a field called AGE_YEARS
Basically I need a python script that says:
If (LINED == 'Yes'):
# Calculate AGE_YEARS to be the difference between LINEDYEAR and the current date
else:
# Calculate AGE_YEARS to be the difference between INSTALLYEAR and the current date
# Below is what I have so far
from datetime import datetime
edit_layer = "AIRDRIE_EDIT.GIS.sGravityMain"
LinedDate = !LINED_YEAR!
InstallDate = !INSTALL_DATE!
CurrentDate = datetime.now()
diff1 = CurrentDate - LinedDate
diff2 = CurrentDate - InstallDate
AgeYears = "getClass(!LINED!)"
# Criteria for how to calculate field
codeblock = """
def getClass(LINED):
if (LINED == 'Yes'):
return diff1
else:
return diff2"""
# calculate age in years
arcpy.management.CalculateField(edit_layer, 'AGE_YEARS', AgeYears, "PYTHON3", codeblock)
The above block shows what I have so far. Any suggestions are appreciated!
Solved! Go to Solution.
Thanks for the help, the issue seemed to be that the script wasn't recognizing the field name as the field, instead it seemed to just be reading it as a string. I couldn't figure it out and I ended up going down a rabbit hole that lead me to using an updatecursor instead. I've listed the code below, hopefully it helps someone.
import arcpy
from datetime import datetime
# Layer being edited
edit_layer = "SanMain"
# Fields being used in the updatecursor
fields = ['LINEDYEAR', 'INSTALLDATE', 'AGE_YEARS', 'LINED']
#Variable showing current date
CurrentDate = datetime.now()
# Update cursor to run through layer and update the AGE_YEARS field with the difference between now and lined or install date
with arcpy.da.UpdateCursor(edit_layer, fields) as cursor:
for row in cursor:
if (row[3] == 'Yes'):
row[2] = round(((CurrentDate - row[0]).total_seconds())/(365.25*24*60*60),2)
elif (row[3] == 'No' or row[3]== None):
row[2] = round(((CurrentDate - row[1]).total_seconds())/(365.25*24*60*60),2)
cursor.updateRow(row)
This might help Populating field based on value of another field
Maybe something like the following:
AGE_YEARS = reclass(!LINED!)
def reclass(LINED):
if(LINED == "YES":
return !LINEDYEAR! - !CURRENTDATE!
else:
return !INSTALLYEAR! - !CURRENTDATE!
Thanks for the suggestion! I've tried something similar (I've edited my post above to show the code) and I'm getting this error:
TypeError: unsupported operand type(s) for -: 'datetime.datetime' and 'SList'
Thanks for the help, the issue seemed to be that the script wasn't recognizing the field name as the field, instead it seemed to just be reading it as a string. I couldn't figure it out and I ended up going down a rabbit hole that lead me to using an updatecursor instead. I've listed the code below, hopefully it helps someone.
import arcpy
from datetime import datetime
# Layer being edited
edit_layer = "SanMain"
# Fields being used in the updatecursor
fields = ['LINEDYEAR', 'INSTALLDATE', 'AGE_YEARS', 'LINED']
#Variable showing current date
CurrentDate = datetime.now()
# Update cursor to run through layer and update the AGE_YEARS field with the difference between now and lined or install date
with arcpy.da.UpdateCursor(edit_layer, fields) as cursor:
for row in cursor:
if (row[3] == 'Yes'):
row[2] = round(((CurrentDate - row[0]).total_seconds())/(365.25*24*60*60),2)
elif (row[3] == 'No' or row[3]== None):
row[2] = round(((CurrentDate - row[1]).total_seconds())/(365.25*24*60*60),2)
cursor.updateRow(row)
I suspect the solution could be using an update cursor (update cursor documentation) - that will go row by row through your data, evaluate the conditions you are testing for, then apply a change in the target field. The form of this would look something like this, this is very back of the napkin sketched out here, so you'll have to work through it and there are probably much more elegant ways to handle this.
fc = path name to your feature class to update
fields = list of fields you need ['LINED','AGE_YEARS']
with arcpy.da.UpdateCursor(fc,fields) as cursor:
for row in cursor:
if row[0]== 'Yes':
lined_date = <calc to get diff1 in your example>
row[1] = lined_date
elif row[0]<> 'Yes':
lined_date = <calc to get diff2 in your example>
row[1] = lined_date
cursor.updateRow(row)