Monday, November 2, 2015

Selecting Features Randomly by Percent or Count in ArcMap

A coworker of mine recently asked for code to select features from a layer at random by percent. I created a function that could be pasted into the Python shell in ArcMap, and then called when the user wanted to make the random selection. I also developed a version to select by count instead of percent. There was a related question on GIS Stackexchage that didn't have an accepted answer, so I posted the code there as well.

The code for a selection by percent:

def SelectRandomByPercent (layer, percent):
    #layer variable is the layer name in TOC
    #percent is percent as whole number  (0-100)
    if percent > 100:
        print "percent is greater than 100"
        return
    if percent < 0:
        print "percent is less than zero"
        return
    import random
    featureCount = float (arcpy.GetCount_management 
                          (layer).getOutput (0))
    count = int (featureCount * float (percent) / float (100))
    oidFldName = arcpy.Describe (layer).OIDFieldName
    delimOidFld = arcpy.AddFieldDelimiters (layer, oidFldName)
    if not count:
        #select zero
        sql = "{0} = -1".format (delimOidFld)
        arcpy.SelectLayerByAttribute_management (layer, "", sql)
        return
    oids = [oid for oid, in arcpy.da.SearchCursor (layer, "OID@")]
    randOids = random.sample (oids, count)
    oidsStr = ", ".join (map (str, randOids))
    sql = "{0} IN ({1})".format (delimOidFld, oidsStr)
    arcpy.SelectLayerByAttribute_management (layer, "", sql)

The code for a selection by count:
def SelectRandomByCount (layer, count):
    #layer is the layer name in TOC
    #count is the count of features to be selected
    import random
    layerCount = int (arcpy.GetCount_management 
                      (layer).getOutput (0))
    if layerCount < count:
        print "input count is greater than layer count"
        return
    oids = [oid for oid, in arcpy.da.SearchCursor (layer, "OID@")]
    oidFldName = arcpy.Describe (layer).OIDFieldName
    delimOidFld = arcpy.AddFieldDelimiters (layer, oidFldName)
    randOids = random.sample (oids, count)
    oidsStr = ", ".join (map (str, randOids))
    sql = "{0} IN ({1})".format (delimOidFld, oidsStr)
    arcpy.SelectLayerByAttribute_management (layer, "", sql)
profile for Emil Brundage at Geographic Information Systems Stack Exchange, Q&A for cartographers, geographers and GIS professionals

1 comment: