Select to view content in your preferred language

Sorting Records

1143
2
Jump to solution
04-10-2014 12:00 PM
JohnDye
Deactivated User
Does anyone know of a good way to sort records by attribute value without the sort_management function?

I need do the following:

  • Iterate through an FC, get the feature with the highest point value

  • Select all of the features within 5 miles of the selected feature,

  • Copy all of those selected features to a new FC

  • Delete the selected from the original FC

  • Continue iterating until the original FC has no features remaining.

I can manage everything except getting the feature with the highest attribute value in the FC. I only have a Basic license so I can't use sort management.

Any ideas?
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
FilipKrál
Frequent Contributor
Hi John,
If your data is in a Geodatabase you can use arcpy.da.SearchCursor, which allows you to specify ORDER BY clause of an SQL Select Statement as part of the sql_clause parameter.

For example, here is a function to get an object ID (or FID for Shapefiles) of the feature with the highest value of an attribute:
import arcpy  def get_id_of_higest(fc, attr):     """Return object ID of a feature with the highest value of attribute attr.     Returns None if fc is an empty feature class.     fc -- feature class (MUST BE STORED IN A GEODATABASE!!!)     attr -- name of the attribute to examine     """     ret = None     with arcpy.da.SearchCursor(fc, ['OID@', attr], sql_clause=(None, 'ORDER BY "' + str(attr) + '" DESC')) as sc:         for row in sc:             ret = row[0]             break     return ret  myfc = r'c:\temp\cities.shp' myattr = 'pop_max' maxido = get_id_of_higest(myfc, myattr) # now you can use maxido to select the feature


You might need to refactor this code to better suit your need and save computational time but hopefully it will help you to get it done.
Filip

View solution in original post

0 Kudos
2 Replies
FilipKrál
Frequent Contributor
Hi John,
If your data is in a Geodatabase you can use arcpy.da.SearchCursor, which allows you to specify ORDER BY clause of an SQL Select Statement as part of the sql_clause parameter.

For example, here is a function to get an object ID (or FID for Shapefiles) of the feature with the highest value of an attribute:
import arcpy  def get_id_of_higest(fc, attr):     """Return object ID of a feature with the highest value of attribute attr.     Returns None if fc is an empty feature class.     fc -- feature class (MUST BE STORED IN A GEODATABASE!!!)     attr -- name of the attribute to examine     """     ret = None     with arcpy.da.SearchCursor(fc, ['OID@', attr], sql_clause=(None, 'ORDER BY "' + str(attr) + '" DESC')) as sc:         for row in sc:             ret = row[0]             break     return ret  myfc = r'c:\temp\cities.shp' myattr = 'pop_max' maxido = get_id_of_higest(myfc, myattr) # now you can use maxido to select the feature


You might need to refactor this code to better suit your need and save computational time but hopefully it will help you to get it done.
Filip
0 Kudos
MattEiben
Deactivated User
You could try using the built in Python sorting method with lists, which you can get from a Search Cursor

Try something like the following.  Keep in mind I haven't actually tested this, but it should give you an idea.

copiedFeatureNumber = 1

featureLayer = arcpy.mapping.Layer(featureClass)

while True:

    # Break out of loop when feature class is empty
    if int(arcpy.GetCount_management(geodatabaseLayer).getOutput(0)) == 0:
        break

    # Get List from Search Cursor
    sortedList = [row for row in arcpy.da.SearchCursor(featureLayer,["OID@","pointValue"])]
    # Sort List by the Point Value
    sortedList = sorted(sortedList, key=lambda x: x[1], reverse=True)
    # Get the FID of the largest Point Value
    FID = sortedList[0][0]

    # Select that Feature
    arcpy.SelectLayerByAttribute_management(featureLayer,"NEW_SELECTION","FID = {0}".format(FID))
    
    # Add to Selection all features within 5 Miles of that Feature
    arcpy.SelectLayerByLocation_management(featureLayer,"WITHIN_A_DISTANCE",featureLayer,"5 Miles","ADD_TO_SELECTION")

    # Make a copy of those features for whatever use desired
    arcpy.CopyFeatures_management(featureLayer,"featureLayer_Num_{0}".format(copiedFeatureNumber))

    # Make a list of the selected FIDs
    FIDList = [row[0] for row in arcpy.da.SearchCursor(featureLayer,["OID@"])]
    
    # Clear Selection
    arcpy.SelectLayerByAttribute_management("address_final_lm","CLEAR_SELECTION")
    
    # Iterate through that Feature Class and remove all features in the selected FID List 
    with arcpy.da.UpdateCursor(featureLayer, ["OID@"]) as updatecursor:
        for row in updatecursor:
            if row[0] in FIDList:
                updatecursor.deleteRow()
    
    copiedFeatureNumber += 1


This probably isn't the most efficient method, but it should get the job done.

Hope this helps!

Matt
0 Kudos