[GIS] How to group values in a field based on range of number using python, and then update the attribute table

arcgis-desktoparcpygroupingpython

An example of what I'm trying to accomplish is described below, however they don't describe how to use the data update cursor to update the attribute column.

data – Group values based on range of number in python – Stack Overflow
https://stackoverflow.com/questions/20437394/group-values-based-on-range-of-number-in-python

fc = r'C:\Users\Test.gdb\Test1a'
print "fc set"
class_field = "Numbers"
name_field = "GroupedID2"
lst = sorted(arcpy.da.SearchCursor(fc, [class_field,name_field]))
class Delta:
    def __init__(self, delta):
        self.last = None
        self.delta = delta
        self.key = 1
    def __call__(self, value):
        if self.last is not None and abs(self.last - value[0]) > self.delta:
            # Compare with the last value (`self.last`)
            # If difference is larger than 2.5, advance to next project
            self.key += 1
        self.last = value[0]  # Remeber the last value.
        return self.key

import itertools
for key, grp in itertools.groupby(lst, key=Delta(2.5)):
    for tup in grp:
        print(tup + ('project{}'.format(key),))
with arcpy.da.UpdateCursor(fc, "GroupedID2") as cursor:
    for row in cursor:
        cursor.updateRow(row)
        print (row[0])

The trouble that I have is that no matter where I place the update cursor, I can't get it to record each row correctly. It will make the entire attribute the last project number or the first project number instead of rows 1-3 project1, 4-6 project2, and 7-8 project3.

This is what the code prints. The feature class remains project 1 but it isn't updated to include the correct project number from the 3rd column.

2014-07-16 07:26:59.135000
fc set
(1279015.0, u'project1', 'project1')
(1279017.5, u'project1', 'project1')
(1279020.0, u'project1', 'project1')
(1279022.5, u'project1', 'project1')
(1279027.5, u'project1', 'project2')
(1279030.0, u'project1', 'project2')
(1279032.5, u'project1', 'project2')
(1279037.5, u'project1', 'project3')
(1279040.0, u'project1', 'project3')
(1279042.5, u'project1', 'project3')

when I alter the code to read this:

import itertools
for key, grp in itertools.groupby(lst, key=Delta(2.5)):
    for tup in grp:
        print(tup + ('project{}'.format(key),))
        test = ('project{}'.format(key))
        with arcpy.da.UpdateCursor(fc, "GroupedID2") as cursor:
            for row in cursor:
                test = row[0]
                cursor.updateRow(row)
                print (row[0])
print(datetime.now()-startTime)

It still keeps it as project 1.

Best Answer

here is an alternative to your solution

#store field values in a new list
newlist=[]
with arcpy.da.SearchCursor(fc, ("valueField")) as scursor:
    for row in scursor:
        newlist.append(row[0])

#find the boundaries between classes
newlist.sort()
limits=[0]
for j in range(newlist):
    if (newlist[j+1]-newlist[j])>2.5:
        limits.append(newlist[j+1])

#update project number inside the boundaries 
for i in range(len(limits)-1):
    with arcpy.da.UpdateCursor(fc, ("GroupedID2"), """ ("valueField" >={0}) and ("valueField" <{1}) """.format(limits[i], limits[i+1]) ) as cursor:
        for row in cursor:
            row[0]='project{}'.format(i)
            cursor.updateRow(row)
Related Question