Is it possible to use arcpy.da.SearchCursor() to get a count of unique features in a field without a dictionary?

So, by this I mean if I have a field called TEXT which contains 10,000 rows populated with either A or B. Can I use the da.SearchCursor to quickly give me the count for the total amount of A in TEXT and B in the TEXT?

I know it is possible to use Summary Statistics or the Get Count tool but these involve having to make a feature layer and then selecting features or kicking out a table. I looking to have a few steps as possible in my script :-)

  • I know you state that you can use the Summary Statistics tool but you don't want to because it involves creating a new table but have you tried using the IN_MEMORY workspace? This is like a simple geodatabase held in RAM so when the script finishes or you shut down ArcMap it's all gone, no temporary data clogging up your hard drive. Worth the investigation? – Hornbydd Aug 8 '14 at 13:54
  • @Hornbydd it's faster to do the calculations in Python directly and store the results in a dict/list/whatever, rather than creating a table and then having to use a SearchCursor on that to get your results. – nmpeterson Aug 8 '14 at 14:04
  • 1
    Out of curiosity, why the specific request to do this "without a dictionary"? Dicts are great! – nmpeterson Aug 8 '14 at 14:36
  • Mainly because its a small tally that's needed as part of a bigger script. I have used dict's in the script, to effectively pivot tables from a CSV file into a FC table, but I'm looking for a very quick and fast running solution to tallying how many of two values are found in on field that appear later in the script. – spk578 Aug 8 '14 at 14:53

Use collections.Counter:

import collections

with arcpy.da.SearchCursor(feature_class, field) as cur:
    count_of_items = collections.Counter(row[0] for row in cur)

print "Sorted items"
print "----"

for item in sorted(count_of_items.items(), key=lambda x:x[1]):
    print "{0:>12} {1:>4}".format(item[0], item[1])
  • I've got it now... with arcpy.da.SearchCursor(fc, field) as cur: count_of_items = collections.Counter(row[0] for row in cur) CountA = count_of_items.items()[0][1] CountB = count_of_items.items()[1][1] for item in sorted(count_of_items.items()): print CountA print CountB – spk578 Aug 11 '14 at 11:45

I think this is the easiest way to do it:

all_values = [r[0] for r in arcpy.da.SearchCursor(table, [field])]
unique_values = set(all_values)
count_dict = {}
for value in unique_values:
    count_dict[value] = all_items.count(value)
  • 3
    This keeps the entire result set in memory unnecessarily. If you just iterate over the cursor and populate the dictionary as you go, you'll avoid having to keep that all in memory. – Jason Scheirer Aug 8 '14 at 14:23

Well if you really want to use a cursor to perform this task, don't want a dictionary, and it's only a couple of known/expected values, you could just loop through each record in the search cursor's resulting dataset and do something like (pseudo code below, adjust to work for your situation and syntax requirements).

aCounter = 0
bCounter = 0
for record in cursorOutput:
    if record[field] == "String A":
        aCounter += 1
    elif record[field] == "String B":
        bCounter += 1

But you can also just use summary statistics GP tool and write the output to a scratch workspace environment and not keep the output, thus possibly mitigating some of your concerns with using that method.

Just a couple of thoughts, hope it helps.

  • This code requires you to have a pre-calculated list of every value that could happen in the cursor, though. – Jason Scheirer Aug 8 '14 at 14:22

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.