Select to view content in your preferred language

Subtract two specific values

4983
22
Jump to solution
10-25-2013 06:12 AM
ClintonCooper1
Deactivated User
I have a table that has several records that I have given a sequence number to based on the find identical tool that creates a new field which creates a new sequence number if they are identical.  Some features are unique while others may have up to 12 identical features.  I created a third filed which is a concatenation of the feat_seq field and an age field of which I can sort to get an order of age from oldest to youngest.  I would like to subtract the first two values, the oldest from the second oldest while not preforming this subtraction if there is less than 1 identical feature.  Additionally, if there are more than 3 identical features, it would only subtract the first two and none of the other ones.  Here is a sample of what the data might look like:

id age newid difference in age
2257 72 225772 n/a
2257 62 225762 10
2258 45 225845 0
2259 58 225958 n/a
2259 57 225957 1
2259 27 225927 n/a
2259 24 225924 n/a


I have found some code/thread (http://forums.arcgis.com/threads/28786-Need-Python-Example-sort-rows-subtract-current-from-next-load...)  that will subtract each value starting from the first value all through the end.  I was wondering if it is possible to specify which rows to subtract and which ones not to subtract using python ?

Clinton
Tags (2)
0 Kudos
22 Replies
ClintonCooper1
Deactivated User
I just indexed the trial data set (I hadn't yet as this was just a small test set).  After I did that and ran it again, and it took me about 3 minutes.... I will try it on my large dataset tonight, and hope that it doesn't extrapolate out to 300 minutes!!  Thank you again!!!

Clinton
0 Kudos
ClintonCooper1
Deactivated User
After reviewing the code and trying it out, it seems to update the first value only of the top two years I am subtracting.  I added a second sql or expression to update the first and second rows.  Here is my new code:



import arcpy
from arcpy import env
env.workspace = r"C:\Users\ccooper\Desktop\DATA.gdb\WAYNE"

table = "WAYNE"

# create empyt list to append ID field
list = []

# iterate through table and append ID to list
with arcpy.da.SearchCursor(table, ["FEAT_SEQ"]) as cursor:
    for row in cursor:
        list.append(row[0])

del row, cursor

#remove duplicate IDs
list = dict.fromkeys(list)
list = list.keys()

#iterate through list
for FEAT_SEQ in list:
    list2 = []
    with arcpy.da.SearchCursor(table, ["FEAT_SEQ", "YEAR_OF_BIRTH", "DIFFERENCE"], "FEAT_SEQ = " + str(FEAT_SEQ)) as cursor:
        for row in cursor:
            #append YEAR_OF_BIRTH to new list
            list2.append(row[1])
    #sort list
    list2.sort()
    try:
        #calculate the difference
        DIFFERENCE = list2[1] - list2[0]
    except:
        DIFFERENCE = ''
    del row, cursor
    try:
        #update table with difference value
        with arcpy.da.UpdateCursor(table, ["FEAT_SEQ", "YEAR_OF_BIRTH", "DIFFERENCE"], "FEAT_SEQ = " + str(FEAT_SEQ) +  AND ("YEAR_OF_BIRTH = " + str(list2[0]) + " OR YEAR_OF_BIRTH = " + str(list2[1]))) as cursor:
            for row in cursor:
                row[2] = DIFFERENCE
                cursor.updateRow(row)
    except:
        pass

del row, cursor


  However, when I run it, I get this runtime error:


Runtime error 
Traceback (most recent call last):
  File "<string>", line 45, in <module>
NameError: name 'row' is not defined



I believe I got the new sql statement right by adding the or expression after the and expression?

Clinton
0 Kudos
JakeSkinner
Esri Esteemed Contributor
Try deleting the row and cursor within the 'try' statement and you should no longer get this error:

try:
   #update table with difference value
   with arcpy.da.UpdateCursor(table, ["FEAT_SEQ", "YEAR_OF_BIRTH", "DIFFERENCE"], "FEAT_SEQ = " + str(FEAT_SEQ) +  AND ("YEAR_OF_BIRTH = " + str(list2[0]) + " OR YEAR_OF_BIRTH = " + str(list2[1]))) as cursor:
            for row in cursor:
                row[2] = DIFFERENCE
                cursor.updateRow(row)
    del row, cursor
except:
    pass
0 Kudos
ClintonCooper1
Deactivated User
Try deleting the row and cursor within the 'try' statement and you should no longer get this error:

try:
   #update table with difference value
   with arcpy.da.UpdateCursor(table, ["FEAT_SEQ", "YEAR_OF_BIRTH", "DIFFERENCE"], "FEAT_SEQ = " + str(FEAT_SEQ) +  AND ("YEAR_OF_BIRTH = " + str(list2[0]) + " OR YEAR_OF_BIRTH = " + str(list2[1]))) as cursor:
            for row in cursor:
                row[2] = DIFFERENCE
                cursor.updateRow(row)
    del row, cursor
except:
    pass


I made your suggested changes, and made a small fix to the sql statement.  However, now it is running though an endless loop and updating all values, not just the first two values in feat_seq.  Do you know what I am missing in the sql statement to make this work?  Thanks in advance!

Clinton
0 Kudos
JakeSkinner
Esri Esteemed Contributor
Can you upload a sample of the table you are working with?
0 Kudos
ClintonCooper1
Deactivated User
Here it is.

Clinton
0 Kudos
JakeSkinner
Esri Esteemed Contributor
I believe the problem was with the SQL Expression.  You will need to specify 'FEAT_SEQ' twice in the query:

FEAT_SEQ = " + str(FEAT_SEQ) +  "AND YEAR_OF_BIRTH = " + str(list2[0]) +  " OR FEAT_SEQ = " + str(FEAT_SEQ) + "AND YEAR_OF_BIRTH = " +  str(list2[1])

Try the following:

try:         #update table with difference value         with arcpy.da.UpdateCursor(table, ["FEAT_SEQ", "YEAR_OF_BIRTH", "DIFFERENCE"], "FEAT_SEQ = " + str(FEAT_SEQ) +  "AND YEAR_OF_BIRTH = " + str(list2[0]) + " OR FEAT_SEQ = " + str(FEAT_SEQ) + "AND YEAR_OF_BIRTH = " + str(list2[1])) as cursor:             for row in cursor:                 row[2] = DIFFERENCE                 cursor.updateRow(row)         del row, cursor except:         pass
0 Kudos
ClintonCooper1
Deactivated User
Thanks, That worked!!
0 Kudos
AllisonBergman
Emerging Contributor
Thank you for posting this information.  I'm also trying to subtract two values with the same id number and then populate the difference field.  I tried this code to understand the thought process before using my own code, because I have different data types for the fields.  Here is the code that I used.  However, it only updates two values in the DIFFERENCE field. 
[5501, 1966, 166]
[5501, 1800, 166]

So my questions are:

1) Can you please tell me what I'm doing wrong with the code? I'd like to see all of the Differences populated instead of just two.
2) Instead of subtracting the two largest numbers, I'd like to subtract the smallest number from the largest number. 
3) On my personal data the FEAT_SEQ is a text field, are there any changes that I need to make to the code to make it work with a text id?

import arcpy
from arcpy import env
env.overwriteOutput = True
env.workspace = r"C:\Users\Test\Desktop\Delete.gdb"

table = "data"

# create empyt list to append ID field
list = []

# iterate through table and append ID to list
with arcpy.da.SearchCursor(table, ["FEAT_SEQ"]) as cursor:
    for row in cursor:
        list.append(row[0])

del row, cursor

#remove duplicate IDs
list = dict.fromkeys(list)
list = list.keys()

#iterate through list
for FEAT_SEQ in list:
    list2 = []
    with arcpy.da.SearchCursor(table, ["FEAT_SEQ", "YEAR_OF_BI", "DIFFERENCE"], "FEAT_SEQ = " + str(FEAT_SEQ)) as cursor:
        for row in cursor:
            #append YEAR_OF_BI to new list
            list2.append(row[1])
    #sort list
    list2.sort()
    try:
        #calculate the difference
        DIFFERENCE = list2[1] - list2[0]
        print list2[1]
        print list2[0]
        print DIFFERENCE
    except:
        DIFFERENCE = ''
    del row, cursor
try:
        #update table with difference value
        with arcpy.da.UpdateCursor(table, ["FEAT_SEQ", "YEAR_OF_BI", "DIFFERENCE"], "FEAT_SEQ = " + str(FEAT_SEQ) +  "AND YEAR_OF_BI = " + str(list2[0]) + " OR FEAT_SEQ = " + str(FEAT_SEQ) + "AND YEAR_OF_BI = " + str(list2[1])) as cursor:
            for row in cursor:
                row[2] = DIFFERENCE
                cursor.updateRow(row)
                print row
        del row, cursor
except:
        pass

print "Finished Script"


Thank you very much for your help...

-Allison
0 Kudos
JakeSkinner
Esri Esteemed Contributor
Hi Allison,

I believe you will just need to put the UpdateCursor within the FOR loop.  Ex:

#iterate through list
for FEAT_SEQ in list:
    list2 = []
    with arcpy.da.SearchCursor(table, ["FEAT_SEQ", "YEAR_OF_BI", "DIFFERENCE"], "FEAT_SEQ = " + str(FEAT_SEQ)) as cursor:
        for row in cursor:
            #append YEAR_OF_BI to new list
            list2.append(row[1])
    #sort list
    list2.sort()
    try:
        #calculate the difference
        DIFFERENCE = list2[1] - list2[0]
        print list2[1]
        print list2[0]
        print DIFFERENCE
    except:
        DIFFERENCE = ''
    del row, cursor
    try:
            #update table with difference value
            with arcpy.da.UpdateCursor(table, ["FEAT_SEQ", "YEAR_OF_BI", "DIFFERENCE"], "FEAT_SEQ = " + str(FEAT_SEQ) +  "AND YEAR_OF_BI = " + str(list2[0]) + " OR FEAT_SEQ = " + str(FEAT_SEQ) + "AND YEAR_OF_BI = " + str(list2[1])) as cursor:
                for row in cursor:
                    row[2] = DIFFERENCE
                    cursor.updateRow(row)
                    print row
            del row, cursor
    except:
            pass

print "Finished Script"
0 Kudos