4

I'm trying to create an update cursor which will take the count of the number of like features in a field and then use that number in a random number generator. The field would look something like that shown below:

**Field**
X
X
X
X
X
Y
Y
Y
Y
Y
Z
Z

As had been suggested by someone on here previously, I tried using collections however, I find that the result is not always accurate with the count total. For example I may have values greater than the total number of like features. I managed to get something working however, now I need something which constrains the random number without replacement and I feel the only way to do this is using collections. My code is shown below:

def sumdict(listvals):
    ddict = collections.defaultdict(int)    
    for val in listvals:
       ddict[val]+=1

    return ddict

dic = sumdict(row[0] for row in arcpy.da.SearchCursor(MyFC, (Field1)))

with arcpy.da.UpdateCursor(MyFC, (Field1, Field2)) as cursor:
    for row in cursor:
        row[1] = sample(1, dic[row[0]])
        cursor.updateRow(row)

Below is an example of what the output should look like, naturally the random numbers will vary.

Field1  Field2
X       2
X       3
X       1
X       5
X       4
Y       3
Y       5
Y       4
Y       2
Y       1
Z       2
Z       1
  • 1
    You are looking for something along the lines of X = 5, Y = 5, Z = 2? How do you want to use the random number generator? What would the output from that look like? – Aaron Aug 15 '14 at 21:28
  • The output would have a random number to use x as an example between 1 and 5 appear 5 times in a different field. Field 2 would contain rows something like 2, 1, 3, 5, 4- all unique. Not sure if that makes sense. – standard Aug 15 '14 at 21:33
  • I know the values will be random but I think a graphic of an example output that could result would make your question clearer. – PolyGeo Aug 15 '14 at 21:44
  • I've edit my question to include a better example illustrating the desired outcome. I can get the random values in Field2 however, they are out of the range for what is contained in Field1. – standard Aug 15 '14 at 21:50
  • OK so I figured out what it's not returning the results I want. Field1 contains many like values, more than I had realized when I had initially viewed the data, hence it's basing the calculation for total like values not just the groups I wanted i.e. there were other X, Y and Z values further down the list of records. I changed Field1 to another field and it works well if I use 'randint' in place of 'sample', which I think is due to needing a population sequence. – standard Aug 15 '14 at 22:13
2

I would take the following approach:

  1. Generate a list of all of the letters and use a Collections() tool to produce a dictionary.

    for letter in [row[0] for row in arcpy.da.SearchCursor(fc, ["Field1"])]:
        cnt[letter] += 1
    

    The Counter() will yield values in the following form:

    Counter({u'Y': 5, u'X': 5, u'Z': 2})
    
  2. Start an UpdateCursor and loop over the paired keys and values e.g. (u'Y', 5)

    for c in cnt.items():
        ...
    
  3. Set logic so that if Field1 is equivalent to the key, write the random integer from 1 through (value) to Field2.

    if row[0] == c[0]:
        row[1] = random.randint(1, c[1])
    

import arcpy, collections, random

fc = r'C:\path\to\featureclass'
cnt = collections.Counter()
for letter in [row[0] for row in arcpy.da.SearchCursor(fc, ["Field1"])]:
    cnt[letter] += 1

with arcpy.da.UpdateCursor(fc, ["Field1", "Field2"]) as cursor:
    for row in cursor:
        for c in cnt.items():
            if row[0] == c[0]:
                row[1] = random.randint(1, c[1])
        cursor.updateRow(row)

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.