2

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.

  • 1
    If you aren't already familiar with using cursors, then coming up with a solution will be tough. Do you understand how the accepted answer works, at least? – Paul Jul 15 '14 at 21:34
  • 3
    Would you be able to edit your question so that it includes a code snippet that works up to where you are stuck, please? – PolyGeo Jul 15 '14 at 21:59
  • I posted the code. Yes, I understand how cursors work. I just can't seem to maintain all of the project numbers that the code comes up with for the respective rows. – user3767931 Jul 16 '14 at 12:39
  • it should be row[0] = test and not test = row[0], but test is not modifiied while you are using your cursor, so you will have the last test value of your for tup in grp as output. your should use a whereclause when you create your update cursor in order to select only the values that are within your range. – radouxju Jul 16 '14 at 12:52
  • @radouxju Ok, so I made changed it to row[0] = test, and you were right. That did make it give the last test value as the output for the whole row. My question is, how would you format the where clause to get a range? My experience with where clauses is getting the max of a value and type of another value. – user3767931 Jul 16 '14 at 17:03
1

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)
  • I tried both of these codes, and the error messages say that floor, minimum, and maximum need to be defined. How do they need to be defined? – user3767931 Jul 17 '14 at 12:30
  • sorry, I didn't specify. floor is a function, but you need to import math module. Minimum and maximum must come from previous code, or manual inputs. – radouxju Jul 17 '14 at 12:47
  • It still gives the same error when I say import math or from math import * – user3767931 Jul 17 '14 at 12:55
  • I used the floor example and got this in the attribute table:1279015 project0 1279017.5 project1 1279020 project2 1279022.5 project3 1279027.5 project5 1279030 project6 1279032.5 project7 1279037.5 project9 1279040 project10 1279042.5 project11 – user3767931 Jul 17 '14 at 13:19
  • isn't it what you need ? if the difference is 2.5 advance to the next project, this it what my code does. You can change the value of the step if you want. – radouxju Jul 17 '14 at 14:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.