Python script to iterate through feature and select each category in a field.

6518
3
12-23-2014 09:55 AM
GeoffreyWest
Occasional Contributor III

I have a category field with 9 categories, what's an easy method to go about selecting 1 of each category?  It can be random features, I just need one of each category.

0 Kudos
3 Replies
JakeSkinner
Esri Esteemed Contributor

Hi Geoffrey,

You can iterate through the Category field and append the value and corresponding OBJECTID to a dictionary.  Then, remove duplicate values from the dictionary leaving only one OBJECTID for each category.  You can then perform the selection based on the dictionary key.

import arcpy
from arcpy import env
env.overwriteOutput = 1
env.workspace = r"C:\temp\python\test.gdb"

fc = "line"

dict = {}

with arcpy.da.SearchCursor(fc, ["OBJECTID", "Category"]) as cursor:
    for row in cursor:
        dict[row[0]] = row[1]

del cursor

dict2 = {}

#remove duplicate values from dictionary
for key,value in dict.items():
    if value not in dict2.values():
        dict2[key] = value

arcpy.MakeFeatureLayer_management(fc, "fcLyr")

#perform selection based on dictionary key
for key in dict2:
    arcpy.SelectLayerByAttribute_management("fcLyr", "NEW_SELECTION", "OBJECTID = " + str(key))
    arcpy.CopyFeatures_management("fcLyr", "fc_" + str(key))

print 'finished'
0 Kudos
RichardFairhurst
MVP Honored Contributor

I would think that to select one of each Category all at once in the layer you would want the code to be like this:

import arcpy  
"""Get the current map layers."""  
mxd = arcpy.mapping.MapDocument("CURRENT"

lyrName = "line" 

"""Find the layer name"""  
lyr = arcpy.mapping.ListLayers(mxd, lyrName)[0

dict = {}  

with arcpy.da.SearchCursor(fc, ["Category", "OID@"]) as cursor:  
    for row in cursor:
        keyValue = row[0]
        if not keyValue in valueDict: 
            dict[keyValue] = row[1
  
del cursor  

#perform selection based on one ObjecctID value from each Category  
whereClause = "OBJECTID IN ("
for key in dict:
   if whereClause == "OBJECTID IN (":
       whereClause = whereClause + str(dict(key))  
   else:
       whereClause = whereClause + ", " + str(dict(key))

whereClause = whereClause + ")"
arcpy.SelectLayerByAttribute_management(lyrName, "NEW_SELECTION", whereClause)

print 'finished' 
0 Kudos
JamesCrandall
MVP Frequent Contributor

The "easiest" being subjective to each person, I've really enjoyed and like to utilize non-ESRI libraries for this kind of grouping.  Specifically, numpy and pandas are excellent at doing these kinds of operations and would allow you to determine unique values that you could then use to make additional selections or other useful tasks.

import arcpy
import numpy
from pandas import *

ws = r"H:\Documents\ArcGIS\Default.gdb"
fc = ws + "\\MyFeatureClass"

#create a NumPy array from the input feature class
nparr = arcpy.da.FeatureClassToNumPyArray(fc, '*')

#create a pandas DataFrame object from the NumPy array
df = DataFrame(nparr, columns=['ObjectId', 'Layer', 'Row', 'Col'])

#access unique values for the field
uniqueValues = numpy.unique(df['Layer'])
for uniqueValue in uniqueValues:
    print uniqueValue