1

I'm trying to loop through a set of lines and select points within .25 miles of them. I just need the count, so I'm trying to put the results into a list I can print out. The relevant code is below.

When I execute the code, it will loop through twice and then print the list called data. There are actually 35 rows it should loop through. If I comment out everything but printing out the name of the route (first line of the loop), it will successfully execute as I intended.

I found a similar question here: Select Layer By Attribute using loop. However, this question simply ended with the poster figuring out that their cursor was tied up. Not sure exactly what that means or how to resolve it.

Why would the loop execute less times than there are rows, but not produce an error?

fc = r'PATH TO FILE'
inlyr = r'PATH TO FILE'
data = {}
field = 'ROUTE'
arcpy.MakeFeatureLayer_management(fc, 'route')
route = 'route'
arcpy.MakeFeatureLayer_management(inlyr, 'addrs')
addrs = 'addrs'
cursor = arcpy.SearchCursor(fc)
for row in cursor:
 print "ROUTE = \'{}\'".format(row.getValue(field))
 arcpy.SelectLayerByAttribute_management(route, "NEW_SELECTION", "ROUTE = \'{}\'".format(row.getValue(field)))
 arcpy.SelectLayerByLocation_management(addrs, 'WITHIN_A_DISTANCE', route, '.25 Miles')
 num = arcpy.GetCount_management(addrs)
 data.update({row.getValue(field):num})
 del num
del cursor
print data
asked Jun 11, 2018 at 19:46
6
  • Can you provide more context for this code? Commented Jun 11, 2018 at 19:51
  • Sure. I edited my original post with the full code. Commented Jun 11, 2018 at 19:56
  • 3
    Whenever I see "cursor only did this x times" my first thought is that the cursor is applied to a layer with a selection. you say fc is PATH TO FILE, but to be sure, it's not actually a layer, is it? Commented Jun 11, 2018 at 20:14
  • 2
    Also num = arcpy.GetCount_management(addrs) will return a result object. You may instead want num = arcpy.GetCount_management(addrs).getOutput (0) Commented Jun 11, 2018 at 20:15
  • 3
    "Old" cursors are effectively deprecated. You should be using arcpy.da.SearchCursor (which has a completely different syntax and use paradigm). Commented Jun 11, 2018 at 20:43

4 Answers 4

2

As a complement to the answer already given it is safer to use AddFieldDelimiters when constructing SQL queries. It could be the reason you are not getting expected outcome or there is something wrong with your data or your assumptions.

Adds field delimiters to a field name to allow for use in SQL expressions.

The field delimiters used in an SQL expression differ depending on the format of the queried data. For instance, file geodatabases and shapefiles use double quotation marks (" "), personal geodatabases use square brackets ([ ]), and enterprise geodatabases don't use field delimiters. The function can take away the guess work in ensuring that the field delimiters used with your SQL expression are the correct ones.

I am assuming ROUTE is a text field:

import arcpy
fc1 = r'C:\Path\to.gdb\feature_class'
fc1_fieldname = 'ROUTE'
fc2 = r'C:\Path\to.gdb\feature_class2'
arcpy.MakeFeatureLayer_management(in_features=fc2, out_layer='fc2lyr')
data = {}
with arcpy.da.SearchCursor(fc1,fc1_fieldname) as cursor:
 for row in cursor:
 arcpy.MakeFeatureLayer_management(in_features=fc1, out_layer='fc1lyr', 
 where_clause="""{0} = '{1}'""".format(
 arcpy.AddFieldDelimiters(datasource=fc1,field=fc1_fieldname), row[0]))
 arcpy.SelectLayerByLocation_management(in_layer='fc2lyr', overlap_type='WITHIN_A_DISTANCE', 
 select_features='fc1lyr', 
 search_distance='0.25 Miles')
 data[row[0]] = int(arcpy.GetCount_management(fc2lyr).getOutput(0))
print data
answered Jun 13, 2018 at 6:48
1
  • Good call! I never work outside of geodatabases (file/SDE), so I always forget about field delimiters. Commented Jun 13, 2018 at 14:44
1

I've rewritten your code using data access cursors and assigning values to variables, where appropriate. Try this, and see if you still get the same result. Don't forget to assign your paths to fc and inlyr.

import arcpy
fc = r'C:\Path\to.gdb\feature_class'
inlyr = r'C:\Path\to\layer.lyr'
data = {}
field = 'ROUTE'
route = 'route'
arcpy.MakeFeatureLayer_management(fc, route)
addrs = 'addrs'
arcpy.MakeFeatureLayer_management(inlyr, addrs)
with arcpy.da.SearchCursor(fc, [field]) as cur:
 for row in cur:
 value = row[0]
 where_clause = "ROUTE = '{}'".format(value)
 print(where_clause)
 arcpy.SelectLayerByAttribute_management(route, "NEW_SELECTION", where_clause)
 arcpy.SelectLayerByLocation_management(addrs, 'WITHIN_A_DISTANCE', route, '0.25 Miles')
 num = int(arcpy.GetCount_management(addrs).getOutput(0))
 data[value] = num
print data
answered Jun 11, 2018 at 20:49
2
  • Thanks for pointing out the usage of depreciated functions. Your code is definitely cleaner than mine. Unfortunately, I'm still getting two loops through the feature layer. Commented Jun 12, 2018 at 18:11
  • 1
    What is the value of the Route field in the third record in the dataset? If you add additional print statements in between each stage, how far along into the second/third loop does it get? Is anything returned by print(arcpy.GetMessages())? Commented Jun 13, 2018 at 20:49
0

Before looking at the technical issue, I should warn you that my proposed solution assumes that you have an unique value for each route. If this is not the case, it would be more efficient to create a list of unique field values, and then loop on this list instead of looping on all features (spatial queries can be heavy, so you should try and reduce their number as much as possible.

My solution is based on the use of geometry object instead of making a new layer feature.

import arcpy
fc1 = r'C:\Path\to.gdb\fc'
field = 'ROUTE'
inlyr = r'C:\Path\to.gdb\other2'#better to point to a feature class than a layer
arcpy.MakeFeatureLayer_management(inlyr, 'lyr')
with arcpy.da.SearchCursor(fc, ['SHAPE@', field]) as cur:
 for row in cur: 
 arcpy.SelectLayerByLocation_management('lyr', 'WITHIN_A_DISTANCE', row[0], '0.25 Miles','NEW_SELECTION')
 data[row[1]] = int(arcpy.GetCount_management('lyr').getOutput(0))
print data
answered Jun 13, 2018 at 20:14
0

Foolowing my first remark about the unicity of the features values, you could simply add one step to extract the unique values in your cursor instead of running several times on the duplicates.

import arcpy
fc = r'C:\Path\to.gdb\feature_class'
inlyr = r'C:\Path\to\layer.shp'
data = {}
field = 'ROUTE'
arcpy.MakeFeatureLayer_management(inlyr, 'lyr')
arcpy.env.overwriteOutput = True #Using overwrite output here to make sure that I create a new selection layer at each iteration
with arcpy.da.SearchCursor(fc, [ field]) as cur:
 uniCur = list(set((cur))) #a set is a collection of unique values, but I convert it back to a list for the iteration
 for row in uniCur: 
 arcpy.MakeFeatureLayer_management(fc , 'lyrroute',"""{0} = '{1}'""".format(arcpy.AddFieldDelimiters(fc,field), row[0])) #if route is not a string field, the use {1} instead of '{1}'
 arcpy.SelectLayerByLocation_management('lyr', 'WITHIN_A_DISTANCE', 'lyrroute' , '0.25 Miles','NEW_SELECTION')
 data[row[0]]= int(arcpy.GetCount_management('lyr').getOutput(0))
 del uniCur
print(data)
answered Jun 14, 2018 at 6:06

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.