1

I am trying to update a field in a (point) feature class (e.g. subLayer) using attributes and spatial proximity from another (line) feature class. For this, I'm currently leveraging arcpy tools and an update cursor. This is currently taking over 30 minutes to run. The subLayer feature class contains 7000 records and transLayer contains 7500 records; so these aren't massive feature classes, though they are continually growing as they are developed. Any suggestions on how to optimize this code?

import arcpy
from arcpy import env
import time
start = time.time()

arcpy.env.OverwriteOutput = True

defaultGdbPath = 'C:\Topo_Check_V5.gdb'


subLayer='C:\Topo_Check_V5.gdb\Subs' #point feature class
transLayer='C:\Topo_Check_V5.gdb\TLS' # line feature class


#add in Line_Count field 
arcpy.AddField_management(subLayer, "Line_Count", "SHORT", "", "", "", "", "NULLABLE", "NON_REQUIRED", "")

#TLineCountField = "Line_Count" 

#where clause
where_13_8 = ' "VT" = 13.8 '

#MakeFeatureLayer

arcpy.MakeFeatureLayer_management(transLayer, "transLayer_lyr")
arcpy.SelectLayerByLocation_management("transLayer_lyr", 'WITHIN_A_DISTANCE', "subLayer_lyr", .000002, "NEW_SELECTION")
arcpy.SelectLayerByAttribute_management ("transLayer_lyr", "SUBSET_SELECTION", where_13_8)


with arcpy.da.UpdateCursor (subLayer, ["Line_Count"]) as LineCountList:
    for subrow in LineCountList:
        result=int(arcpy.GetCount_management("transLayer_lyr").getOutput(0))
        #print result
        subrow[0] = result
        LineCountList.updateRow(subrow)
print "Line_Count Updated"
del LineCountList

end = time.time()
print (end - start)/60

In an effort to speed this up, I got a little ahead of myself and took advice to bring the selection statements out of the for loop. Although this did speed up the processing time, I ended up losing the functionality of the original script. I do want to update the unique count of all selected transLayer features (here based on proximity, but for other blocks also based on proximity and attribute data) unique to each record in the the sublayer feature class.

Here is the script that I would like to optimize. Maybe using a spatial join route rather than an update cursor will be the most efficient way to go. I am open to deviating from arcpy if there may be a better Python alternative. I am also curious if dictionaries could help speed things up.

import arcpy
from arcpy import env
import time
start = time.time()

arcpy.env.OverwriteOutput = True

defaultGdbPath = 'C:\Topo_Check_V5.gdb'


subLayer='C:\Topo_Check_V5.gdb\Subs' #point feature class
transLayer='C:\Topo_Check_V5.gdb\TLS' # line feature class
ppLayer='C:\Topo_Check_V5.gdb\PPS' #point feature class




###### Line Counts: Count of connecting lines within distance of point feature class ################

#add in Line_Count field 
arcpy.AddField_management(subLayer, "Line_Count", "SHORT", "", "", "", "", "NULLABLE", "NON_REQUIRED", "")

TLineCountField = "Line_Count" 

#MakeFeatureLayer
arcpy.MakeFeatureLayer_management(transLayer, "transLayer_lyr")


with arcpy.da.UpdateCursor (subLayer, [TLineCountField, "SHAPE@"]) as LineCountList:
    for subrow in LineCountList:
        arcpy.SelectLayerByLocation_management("transLayer_lyr", 'WITHIN_A_DISTANCE', subrow[1], .000002, "NEW_SELECTION")
        result=int(arcpy.GetCount_management("transLayer_lyr").getOutput(0))
        #print result
        subrow[0] = result
        LineCountList.updateRow(subrow)
print "Line_Count Updated"
del LineCountList

closed as too broad by PolyGeo May 19 '17 at 21:27

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 3
    Do you need to get the count of features in transLayer_lyr for every record in subLayer? Try getting the count outside of your cursor, then set the value to subrow[0] inside the cursor. – Fezter May 16 '17 at 22:50
  • 1
    It looks like you're assigning all rows the same value. CalculateField should work faster than a cursor. – Bjorn May 16 '17 at 22:52
  • Please use a new question to ask an additional question rather than doing it as an update to your original. As per the Tour there should be only one question per question. – PolyGeo May 19 '17 at 21:29
4

I would take the following line of code:

result=int(arcpy.GetCount_management("transLayer_lyr").getOutput(0))

And put it outside your cursor. It just seems like this would return the same result all the time anyway, so your code would look like this:

arcpy.MakeFeatureLayer_management(transLayer, "transLayer_lyr")
arcpy.SelectLayerByLocation_management("transLayer_lyr", 'WITHIN_A_DISTANCE', "subLayer_lyr", .000002, "NEW_SELECTION")
arcpy.SelectLayerByAttribute_management ("transLayer_lyr", "SUBSET_SELECTION", where_13_8)
result=int(arcpy.GetCount_management("transLayer_lyr").getOutput(0))

with arcpy.da.UpdateCursor (subLayer, ["Line_Count"]) as LineCountList:
    for subrow in LineCountList:
        subrow[0] = result
        LineCountList.updateRow(subrow)

Or as commented by @Bjorn, you could try using the Field Calculator. It may be faster, but in my experience cursors are often faster. Especially when updating multiple fields.

  • Oops. I had forgotten to add this update to the code sample in the posting. Thanks! This is helpful. Via the arcpy.CalculateField_management route, is it possible to use attribute values from another feature class to update a field without incorporating a spatial join?...or maybe a spatial join would be a better route? – Tess Gardner May 16 '17 at 23:39
  • 3
    @TessGardner, if this answer was useful to you, please accept it. Also, rather than asking a question as a comment where only I am notified, please ask a new question. That way, you'll benefit from the help of the entire GIS.SE community. – Fezter May 16 '17 at 23:44

Not the answer you're looking for? Browse other questions tagged or ask your own question.