Select to view content in your preferred language

SelectLayerByLocation blowing out

209
3
4 weeks ago
JeffHanson2
New Contributor III

I'm trying to take a point in a search cursor and then find what section it is in.   I have a bioFC and a "sec_lyr" and I am passing in the feature from the cursor - looping through the cursor.   It is not working.   How can I iterate one point feature at a time?

 

    cursor = arcpy.da.SearchCursor(bioFC, ["Twp_Sec_Rng"])
    arcpy.MakeFeatureLayer_management(secFC, "sec_lyr")
    # loop one, is a search cursor
    print("Processing data...")
    for fea in cursor:
        arcpy.SelectLayerByLocation_management("sec_lyr", "intersect", fea)
0 Kudos
3 Replies
DavidSolari
Occasional Contributor III

If you have a bunch of features and you want to see their spatial relation to another set of features just use the Spatial Join tool. You can run through the results with a cursor but it'll run much faster, especially as the size of your datasets expand.

0 Kudos
DuncanHornby
MVP Notable Contributor

Firstly when posting code please use the syntax button "</>" accessible via the 3 dots button to make your code clearer. No one should be struggling to read your poorly formatted code. You can always go back an improve your question via the edit post button.

Your code is flawed, a cursor returns a ROW object and the select layer by location tool takes a Feature Layer as its third parameter, you need to be reading the help file parameter section of a tool to understand what its required inputs are.

A great thing about the help file, is the help it gives! Keep scrolling down the page and you will always see a code sample section, study that.

So as your cursor is churning out rows and not layers a better solution is what @DavidSolari  suggests, do a spatial join and search over that. If you write the output of the spatial join to memory workspace you don't have to worry about cleaning up after yourself.

0 Kudos
HaydenWelch
Occasional Contributor II

If you're trying to make a selection in a map the other advice is good. If you want to update the underlying data with Cursors, you'd do it like this:

 

import arcpy   

secFC = "<path>"
bioFC = "<path>"
bioDesc = arcpy.Describe(bioFC)

# Get BIO FC fields
bioFields = [f.name for f in bioDesc.fields]

# Add Twp_Sec_Rng field if not present
if 'Twp_Sec_Rng' not in bioFields:
    arcpy.AddField_management(bioFC, "Twp_Sec_Rng", "TEXT", field_length=255)

print("Processing data...")

# Create a dictionary of sections with their polygons
secs: dict[str,arcpy.Polygon] =\
    {
        row[1]: row[0]
        for row in arcpy.da.SearchCursor(secFC, ["SHAPE@", "Twp_Sec_Rng"])
    }

# Iterate Sections
for sec_id, sec_shape in secs.items():
    
    # Use spatial filter to update only the rows within the section
    with arcpy.da.UpdateCursor(bioFC, ["Twp_Sec_Rng"], spatial_filter=sec_shape, spatial_relationship="INTERSECTS") as cursor:
        for row in cursor:
            row[0] = sec_id
            cursor.updateRow(row)

Also if your section table is really big and can't fit in memory, you can modify that initial secs dictionary to be a generator:

 

import arcpy   
from typing import Generator

secFC = "<path>"
bioFC = "<path>"
bioDesc = arcpy.Describe(bioFC)

# Get BIO FC fields
bioFields = [f.name for f in bioDesc.fields]

# Add Twp_Sec_Rng field if not present
if 'Twp_Sec_Rng' not in bioFields:
    arcpy.AddField_management(bioFC, "Twp_Sec_Rng", "TEXT", field_length=255)

print("Processing data...")

# Create a Generator for Sections. This is more memory efficient if the number of sections is very large.
secs: Generator[tuple[str,arcpy.Polygon], None, None] =\
    (
        (row[1], row[0])
        for row in arcpy.da.SearchCursor(secFC, ["SHAPE@", "Twp_Sec_Rng"])
    )

# Iterate Sections
for sec_id, sec_shape in secs:
    
    # Use spatial filter to update only the rows within the section
    with arcpy.da.UpdateCursor(bioFC, ["Twp_Sec_Rng"], spatial_filter=sec_shape, spatial_relationship="INTERSECTS") as cursor:
        for row in cursor:
            row[0] = sec_id
            cursor.updateRow(row)

 

0 Kudos