Select to view content in your preferred language

Sort feature class field permanently

2118
14
05-16-2023 03:13 PM
2Quiker
Frequent Contributor

I need to permanently sort a feature class field so I can add a sequential number based on the sort. I know I can use the sort tool, but I want to sort the existing feature without having to create another feature class. I am able to do the sequential number with the following but I need the feature class "Sub_Name" sorted. anyone have an example of how to accomplish this?

 

import arcpy
from itertools import count
cntr = count()

fc = 'C:\Temp\SUBS.shp'
with arcpy.da.UpdateCursor(fc,["ID","SUB_NAME"],sql_clause=(None,"ORDER BY SUB_NAME")) as cur:
    for i, j in cur:
        cur.updateRow([next(cntr), j])

 

0 Kudos
14 Replies
BlakeTerhune
MVP Regular Contributor

No, I'm asking about the source data. How do you create the SUBS.shp?

0 Kudos
2Quiker
Frequent Contributor

Sorry, it derived from a feature class in a geodatabase.

I preform a selection by location, then I export the selected features to the shapefile.

0 Kudos
BlakeTerhune
MVP Regular Contributor

Maybe try something like this then.

import arcpy
import os

source_fc = r"C:\Temp\some_gdb\SUBS"
sort_field_name = "SUB_NAME"

# Make new feature class for ordered rows.
out_fc = arcpy.management.CreateFeatureclass(
    out_path=os.path.dirname(source_fc),
    out_name="SUBS_ordered",
    template=source_fc
)

# Insert the rows ordered by sub_name
source_fc_fields = [f.name for f in arcpy.ListFields(source_fc)]
with arcpy.da.SearchCursor(source_fc, "*", sql_clause=(None, f"ORDER BY {sort_field_name}")) as s_cursor:
    with arcpy.da.InsertCursor(out_fc, "*") as i_cursor:
        for row in s_cursor:
            i_cursor.insertRow(row)
0 Kudos
2Quiker
Frequent Contributor

I tried to incorporate you suggestion, but I ran into an issue with the Global ID. At least I believe that is the issue.

TypeError: sequence size must match size of the row.

 

 

 

import arcpy, os

project = arcpy.mp.ArcGISProject("CURRENT")

arcpy.env.workspace = os.path.dirname(project.filePath)
wp = os.path.dirname(project.filePath)
outPath = r'C:\Temp\Scratchworkspace.gdb'

scr = 'SUBS'
sortedTableName = 'SUBS_ordered'
arcpy.management.MakeFeatureLayer("SUBS", "memory\SubsLyr")
arcpy.SelectLayerByLocation_management("SUBS", "WITHIN_A_DISTANCE", "SUBJECT_PROPERTY", "1 Mile", "NEW_SELECTION")

arcpy.analysis.Select("SUBS", r"memory/SubLayer1")

#--check if output feature class exists, if not, create it
if not os.path.exists(os.path.join(outPath,sortedTableName)):
    out_fc = arcpy.management.CreateFeatureclass(outPath,out_name="SUBS_ordered", template=scr)
else:
    try:
        arcpy.DeleteRows_management(os.path.join(outPath,"SUBS_ordered"))
    except:
        pass
    
source_fc = r"memory/SubLayer1"
sort_field_name = "SUB_NAME"
source_fc_fields = [f.name for f in arcpy.ListFields(scr)]
with arcpy.da.SearchCursor(source_fc, "*", sql_clause=(None, f"ORDER BY {sort_field_name}")) as s_cursor:
    with arcpy.da.InsertCursor(sortedTableName, "*") as i_cursor:
        for row in s_cursor:
            i_cursor.insertRow(row)

 

 

 

The "SUBS" is in SDE geodatabase and has GlobalID .

The "SUBS_ordered" in a file geodatabase doesn't have a GlobalID.

How can I leave out the GlobalID or other fields?

 

The other difference between the two is.

SubLayer1: Shape_STArea__ , Shape_STLength__

SUBS_ordered : Shape_Area, Shape_Length

 

0 Kudos
BlakeTerhune
MVP Regular Contributor

They should have the same fields if you're creating the output using the subs as a template. It was hard to follow your code because there seemed to be some unused lines, redundancies, and too many different names. I did my best to refactor it. If there's a GlobalID field in Subs, it should create a GlobalID field in the Subs_Ordered output too.

import arcpy
import os

project = arcpy.mp.ArcGISProject("CURRENT")

arcpy.env.workspace = os.path.dirname(project.filePath)
arcpy.env.overwriteOutput = True
outPath = r'C:\Temp\Scratchworkspace.gdb'

source_fc = "SUBS"
sortedTableName = "SUBS_ordered"

# Select subs by location to subject property.
arcpy.management.MakeFeatureLayer(source_fc, "SubsLyr")
arcpy.management.SelectLayerByLocation(
    in_layer="SubsLyr",
    overlap_type="WITHIN_A_DISTANCE",
    select_features="SUBJECT_PROPERTY",
    search_distance="1 Mile",
    selection_type="NEW_SELECTION"
)

# Make new feature class for ordered rows.
out_fc = arcpy.management.CreateFeatureclass(
    out_path=outPath,
    out_name=sortedTableName,
    template="SubsLyr"
)

# Read through the sorted selection of subs and insert them into the output feature class.
with arcpy.da.SearchCursor("SubsLyr", "*", sql_clause=(None, "ORDER BY SUB_NAME")) as s_cursor:
    with arcpy.da.InsertCursor(sortedTableName, "*") as i_cursor:
        for row in s_cursor:
            i_cursor.insertRow(row)
0 Kudos