Update Cursor not honoring selection in a for loop

1604
5
06-28-2019 08:19 PM
wwnde
by
Occasional Contributor

I have the following table of objects

OBJECTIDConcIDstartfinishDateRangeCat
2ASPELBJNMILAPMT27/06/201811/8/20181000
9ASPELBJNMIKLKIY22/08/201831/08/20181000
16ASPELBJNMIHDOKK12/8/201830/09/20181000
23ASPELBJNMIXMCZW22/08/201820/10/20181000
6BKRKAVQTZCFCBES1/7/201815/08/20181000
13BKRKAVQTZCNHQGW24/08/20184/9/20181000
20BKRKAVQTZCLVUSS9/8/20184/10/20181000
27BKRKAVQTZCRQVNN18/08/201824/10/20181000
7FKKTHEJGCYIHORM2/7/201820/08/20181000
14FKKTHEJGCYAZFEV28/08/20188/9/20181000
21FKKTHEJGCYYAVOY4/8/201829/09/20181000
28FKKTHEJGCYAMWAX16/08/201822/10/20181000
5JUNRNEXCRGQCOWV30/06/201825/08/20181000
12JUNRNEXCRGAOYNL25/08/20189/9/20181000
19JUNRNEXCRGCGCHK4/8/20183/10/20181000
26JUNRNEXCRGIQYGJ12/8/201826/10/20181000

I need to recursively run through calculating the min start date from 'start ' for a group of 'Conc' and finding the 'DateRange' by subtracting the min start date from 'finish'. Every time the  DateRage  becomes equal or less than 60 days,  the Cat should increase by 1 for each group of Concs. Consequent loop should then calculate a new min start date. This should continue till when it is not possible to get a new  DateRage  for  for a group of 'Conc. At the start,  my code defaults  DateRange to 100 and Cat to 0 at the start. 

I have come up with the following code. It runs but seems to honor the outer loop on line 40 but exits without executing executing aspects of inner loop at line 54.

import arcpy
from datetime import datetime
from datetime import datetime as dt
from datetime import timedelta
import time
from datetime import date
#Variables Start
arcpy.env.workspace = r'E:\Classify\New File Geodatabase.gdb'
fc= 'Classifyjoin212'
field =['Conc','ID']
fields = ['start', 'finish', 'DateRange', 'Cat']
Classifyjoin = "Classifyjoin"
Classifyjoin__2_ = Classifyjoin

#Def function

def min_cat(b=datetime.now() , m=datetime.now() ):
    """This function calculates the date range between earliest start in a category to the exact finish date of an individual member"""""
    return(b-m).days
#print min_cat(b=dt.strptime('2019-06-26', '%Y-%m-%d').date(),  m=dt.strptime('2018-07-26', '%Y-%m-%d').date())




#temp_lyr = arcpy.MakeFeatureLayer_management(fc, "temp_lyr") #If using a fc in gdb
temp_lyr= arcpy.MakeTableView_management(fc, "temp_lyr")
listdates = []
listCat =[]

#Variables end


ud = {}

with arcpy.da.SearchCursor(fc, field) as rows:
    for row in rows:
        if row[0] not in ud:
            ud[row[0]] = row[1]
          
for k in ud:
            
    
    where_clause="Conc IN( '%s')" % k #+ "AND ID IN( '%s')" %v
    #print(where_clause)
    kala = arcpy.SelectLayerByAttribute_management(temp_lyr, 'NEW_SELECTION', where_clause)#Carry out the selection
    cnt = arcpy.GetCount_management(temp_lyr) # Counting the selected and copied features
    print("The number of selected records is: " + str(cnt))
    
    


    with arcpy.da.UpdateCursor(kala, fields) as cursor:
            
            for row in cursor:
                if row[2]>60:
                    listdates.append(row[0])

                    pg =min(listdates)#.date()
                    jup = '{}'.format(pg)
                    jop = dt.strptime(jup, '%Y-%m-%d %H:%M:%S').date()
                    
                    bg = '{}'.format(row[1])
                    job = dt.strptime(bg, '%Y-%m-%d %H:%M:%S').date()
                    a =min_cat(b= job, m=jop)
                    row[2] = a
                    cursor.updateRow(row)
                    #continue
                elif row[2]<=60:
                    listCat.append(row[3])
                    jp =min(listCat)
                    kp = int('{}'.format(jp))
                    kp +=1
                    row[3] = kp
                    cursor.updateRow(row)
                    continue                                  
                        #break
            arcpy.SelectLayerByAttribute_management(temp_lyr, "CLEAR_SELECTION")
                    #del row
                    
            del cursor
                

print ("finished")
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The outcome with the code as it is; updates both the DateRange and cat ones. 

Any other way around it?

0 Kudos
5 Replies
JoshuaBixby
MVP Esteemed Contributor

Are you using ArcMap or Pro?  If the latter, try upgrading to 2.4 because the earlier versions had known defects with selection sets not being honored by cursors in some situations.

wwnde
by
Occasional Contributor

Thanks Joshua, this is happenning in both ArcMap 10.5.1 Advansed and

ArcPro. Havent updated Pro for two months. Will try that.

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

I am not aware of any selection set defects in ArcMap, so I will take a closer look at your code this week.

0 Kudos
wwnde
by
Occasional Contributor

I put the code through ArcPro 2.4 and didnt loop through either. I am

looking into the inner loop because thats where I believe I have an issue.

Any help will be appreciated.

0 Kudos
wwnde
by
Occasional Contributor

I have made several attempt to get the code working. Not successful.

First Option: Runs well, updates first loop correctly and does nothing to the rest of items in the selection

import arcpy
from datetime import datetime
from datetime import datetime as dt
from datetime import timedelta
import time
from datetime import date
#Variables Start
arcpy.env.workspace = r'C:\Users\williamk\Desktop\Delete\datap\New File Geodatabase.gdb'
fc= 'Classifyjoin212'
field =['Conc','ID']
fields = ['start', 'finish', 'DateRange', 'Cat']
Classifyjoin = "Classifyjoin"
Classifyjoin__2_ = Classifyjoin

#Def function

def min_cat(b=datetime.now() , m=datetime.now() ):
    """This function calculates the date range between earliest start in a category to the exact finish date of an individual member"""""
    return(b-m).days
#print min_cat(b=dt.strptime('2019-06-26', '%Y-%m-%d').date(),  m=dt.strptime('2018-07-26', '%Y-%m-%d').date())




#temp_lyr = arcpy.MakeFeatureLayer_management(fc, "temp_lyr") #If using a fc in gdb
temp_lyr= arcpy.MakeTableView_management(fc, "temp_lyr")


#Variables end


ud = {}

with arcpy.da.SearchCursor(fc, field) as rows:
    for row in rows:
        if row[0] not in ud:
            ud[row[0]] = row[1]
          
for k in ud:
            
    
    where_clause="Conc IN( '%s')" % k #+ "AND ID IN( '%s')" %v
    #print(where_clause)
    kala = arcpy.SelectLayerByAttribute_management(temp_lyr, 'NEW_SELECTION', where_clause)#Carry out the selection
    cnt = arcpy.GetCount_management(temp_lyr) # Counting the selected and copied features
    print("The number of selected records is: " + str(cnt))
    
    
   
    listdates = []
    listCat =[]
    bv =[]
    with arcpy.da.UpdateCursor(fc, fields) as cursor:
            
        for row in cursor:
            #while row[3]==0:
            if row[3]==-1:
                listdates.append(row[0])

                pg =min(listdates)#.date()
                jup = '{}'.format(pg)
                jop = dt.strptime(jup, '%Y-%m-%d %H:%M:%S').date()
                
                bg = '{}'.format(row[1])
                job = dt.strptime(bg, '%Y-%m-%d %H:%M:%S').date()
                a =min_cat(b= job, m=jop)
                row[2] = a
                cursor.updateRow(row)
                
    #del cursor, row    
                    
    with arcpy.da.UpdateCursor(fc, fields) as innercursor:
        for rows in innercursor:
           if rows[2] <=60:
                listCat.append(rows[3])
                jp =min(listCat)
                kp = int('{}'.format(jp))
                kp +=1
                rows[3] = kp
                innercursor.updateRow(rows)
                            
                    
    #del innercursor, rows
     
print ("finished")
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Second option throws a traceback on line 79:

rows[3] = u
TypeError: 'da.SearchCursor' object does not support item assignment
>>>

import arcpy
from datetime import datetime
from datetime import datetime as dt
from datetime import timedelta
import time
from datetime import date
#Variables Start
arcpy.env.workspace = r'C:\Users\williamk\Desktop\Delete\datap\New File Geodatabase.gdb'
fc= 'Classifyjoin212'
field =['Conc','ID']
fields = ['start', 'finish', 'DateRange', 'Cat']
Classifyjoin = "Classifyjoin"
Classifyjoin__2_ = Classifyjoin

#Def function

def min_cat(b=datetime.now() , m=datetime.now() ):
    """This function calculates the date range between earliest start in a category to the exact finish date of an individual member"""""
    return(b-m).days
#print min_cat(b=dt.strptime('2019-06-26', '%Y-%m-%d').date(),  m=dt.strptime('2018-07-26', '%Y-%m-%d').date())

l =[]
def categories (l):
    
    jp =min(l)
    kp = int('{}'.format(jp))
    kp +=1
    return kp
#k = [row[3] for row in arcpy.da.SearchCursor(fc, ["start", "finish", "DateRange", "Cat"]) if row [2]<60]
#print categories(k) #(fc, field) 


#temp_lyr = arcpy.MakeFeatureLayer_management(fc, "temp_lyr") #If using a fc in gdb
temp_lyr= arcpy.MakeTableView_management(fc, "temp_lyr")


#Variables end


ud = {}

with arcpy.da.SearchCursor(fc, field) as rows:
    for row in rows:
        if row[0] not in ud:
            ud[row[0]] = row[1]
          
for k in ud:
            
    
    where_clause="Conc IN( '%s')" % k #+ "AND ID IN( '%s')" %v
    #print(where_clause)
    kala = arcpy.SelectLayerByAttribute_management(temp_lyr, 'NEW_SELECTION', where_clause)#Carry out the selection
    cnt = arcpy.GetCount_management(temp_lyr) # Counting the selected and copied features
    print("The number of selected records is: " + str(cnt))
    
    
   
    listdates = []
    listCat =[]
    bv =[]
    k = [row[3] for row in arcpy.da.SearchCursor(fc, ["start", "finish", "DateRange", "Cat"]) if row [2]<60]
    with arcpy.da.UpdateCursor(fc, fields) as cursor:
            
        for row in cursor:
            #while row[3]==0:
            if row[3]==-1:
                listdates.append(row[0])

                pg =min(listdates)#.date()
                jup = '{}'.format(pg)
                jop = dt.strptime(jup, '%Y-%m-%d %H:%M:%S').date()
                
                bg = '{}'.format(row[1])
                job = dt.strptime(bg, '%Y-%m-%d %H:%M:%S').date()
                a =min_cat(b= job, m=jop)
                row[2] = a
                cursor.updateRow(row)
                u = categories(k)
                rows[3] = u
                innercursor.updateRow(rows)
                
    del cursor, row    


     
print ("finished")‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

@joshua Bixby , @Anonymous User Fairhurst  Is there away I can make the list comprehension mutable for it to allow me update cursor using the  value I call at line 78?  I tried lots of  @Anonymous User Fairhurst's Turbo Charging Data with Python but haven't been successful?

Any one with an idea?

0 Kudos