I have the following table of objects
OBJECTID Conc ID start finish DateRange Cat 2 ASPELBJNMI LAPMT 27/06/2018 11/8/2018 100 0 9 ASPELBJNMI KLKIY 22/08/2018 31/08/2018 100 0 16 ASPELBJNMI HDOKK 12/8/2018 30/09/2018 100 0 23 ASPELBJNMI XMCZW 22/08/2018 20/10/2018 100 0 6 BKRKAVQTZC FCBES 1/7/2018 15/08/2018 100 0 13 BKRKAVQTZC NHQGW 24/08/2018 4/9/2018 100 0 20 BKRKAVQTZC LVUSS 9/8/2018 4/10/2018 100 0 27 BKRKAVQTZC RQVNN 18/08/2018 24/10/2018 100 0 7 FKKTHEJGCY IHORM 2/7/2018 20/08/2018 100 0 14 FKKTHEJGCY AZFEV 28/08/2018 8/9/2018 100 0 21 FKKTHEJGCY YAVOY 4/8/2018 29/09/2018 100 0 28 FKKTHEJGCY AMWAX 16/08/2018 22/10/2018 100 0 5 JUNRNEXCRG QCOWV 30/06/2018 25/08/2018 100 0 12 JUNRNEXCRG AOYNL 25/08/2018 9/9/2018 100 0 19 JUNRNEXCRG CGCHK 4/8/2018 3/10/2018 100 0 26 JUNRNEXCRG IQYGJ 12/8/2018 26/10/2018 100 0
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?
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.
Thanks Joshua, this is happenning in both ArcMap 10.5.1 Advansed and
ArcPro. Havent updated Pro for two months. Will try that.
I am not aware of any selection set defects in ArcMap, so I will take a closer look at your code this week.
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.
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?