1

I have a script using a Search Cursor to iteratively make copies of individual features for use as inputs in a geoprocessing tool, e.g.,

fc = <feature class>
arcpy.MakeFeatureLayer_management(fc, 'layer')
with arcpy.da.SearchCursor('layer', [<field>]) as cursor:
    for row in cursor:
           arcpy.SelectLayerByAttribute_management('layer', 'NEW_SELECTION', '{}={}'.format(<field>, row[0])
           arcpy.CopyFeatures_management('layer', 'feature')
           arcpy.<geoprocessing tool>('feature', <output>)

It runs, but is running on a large input feature class over a large raster. I thought I could speed up the script by dropping the feature copying, but can't figure out how to use a cursor row as a geoprocessing input. Is this possible?

Executing the geoprocessing tool on selected features appears to use the extent of the entire input feature class in the raster analysis, slowing the script down dramatically.

  • Yes, selections are honored by geoprocessing tools, run your <geoprocessing tool>('layer') and it will use only the selected features. Are there duplicates in <field> value? If so, make a dict or list first then loop through the list (or dict) instead of doing it inside your cursor. – Michael Stimson Jun 7 '18 at 0:40
1

I recommend a procedure like this:

fc = <feature class>
arcpy.MakeFeatureLayer_management(fc, 'layer')

AllValues = [] # an empty list to contain the unique values
with arcpy.da.SearchCursor('layer', [<field>]) as cursor:
    for row in cursor:
        if row[0] not in AllValues:
            # if the value isn't already in the list then add it
            AllValues.append(row[0])

# loop through all the unique values
for Value in AllValues:
    arcpy.SelectLayerByAttribute_management('layer', 'NEW_SELECTION', '{}={}'.format(<field>, Value))
    # generate the minimum bounding geometry for this layer
    arcpy.MinimumBoundingGeometry_management('layer','in_memory\\temp','ENVELOPE')

    # use the extent of the bounding geometry as the geoprocessing extent
    desc = arcpy.Describe('in_memory\\temp')
    arcpy.env.extent = desc.extent

    arcpy.<geoprocessing tool>('layer', <output>)

    arcpy.Delete_management('in_memory\\temp') # Clean up
    arcpy.env.extent = 'MAXOF' # reset to 'big' so the next MBG isn't affected.

Generating a list of only the unique values in your field then iterate each unique value in the list.. otherwise your loop will run for each feature producing the same output multiple times, overwriting each previous iteration (or crashing if arcpy.env.overwriteOutput == False).

Edit I have included in the code reducing the extent to just the selected features using Minimum Bouning Geometry to an in_memory feature class then getting the extent by describing the minimum polygon.

  • I forgot to mention the key issue and have edited my original post to include it. The geoprocessing tool I'm running is Tabulate Area over a very large raster. Even with single features selected, the processing time is very slow. I'm assuming that is because the tool is processing the raster using the full extent of the input features. Maybe a better question is, 'Can I use geometry from a Search Cursor to limit the processing extent of a Spatial Analyst geoprocessing tool?' – Ian Yau Jun 7 '18 at 0:59
  • 1
    Absolutely. You can create a minimum bounding geometry in_memory, describe the data and set your arcpy.env.extent = desc.extent which will limit the processing of the raster. Would you like that edited into the script? – Michael Stimson Jun 7 '18 at 1:11
  • Excellent! Thank you so much. This cut the processing time from 32s/record down to 19s/record. Over 38,000+ records, that really adds up! – Ian Yau Jun 7 '18 at 16:53

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.