Select to view content in your preferred language

Converting Arcade Script to Python

433
5
Jump to solution
07-29-2024 09:45 AM
CaitlinSjodin
Emerging Contributor

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!

 

Tags (1)
0 Kudos
1 Solution

Accepted Solutions
CaitlinSjodin
Emerging Contributor

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)

View solution in original post

0 Kudos
5 Replies
Ed_
by MVP Regular Contributor
MVP Regular Contributor

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!

 

 

Question | Analyze | Visualize
0 Kudos
CaitlinSjodin
Emerging Contributor

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'

 

Ed_
by MVP Regular Contributor
MVP Regular Contributor

That's a datatype support error 

Maybe look into this  and this 

Question | Analyze | Visualize
0 Kudos
CaitlinSjodin
Emerging Contributor

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)
0 Kudos
clt_cabq
Frequent Contributor

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)