How to use "arcpy.SelectLayerByLocation_management" efficiently?

3405
5
07-08-2015 11:49 PM
SuryaKant
New Contributor III

I have two layer Parcels(polygon) with fields objectid, parcel_name, parcel_id and location and Sites(point) with objectid field. I want to write a csv file with the Sites objectid field with the parcel_name and parcel_id if the point falls inside any parcel polygon like 2034, ABC, ABC_12 (Site's objectid, Parcels's parcel_name, Parcels's parcel_id).

import arcpy
import os

arcpy.env.overwriteOutput = True


def main():
    """ main function"""
    try:
        fc = r'Database Connections\Test.sde\UserName.AllData\UserName.Parcels' # arcpy.GetParameter(0)
        parcel_name = 'Parcel_Name' #arcpy.GetParameterAsText(1)
        parcel_id = 'Parcel_ID' #arcpy.GetParameterAsText(2)
        sites_fc = r'Database Connections\Test.sde\UserName.AllData\UserName.Sites' #arcpy.GetParameter(3)
        output_path = os.path.join(os.path.dirname(__file__), 'Name_and_ID.csv')


        ftr_name = os.path.basename(str(sites_fc)).split('.')[-1]
        sites_fc_local = arcpy.MakeFeatureLayer_management(sites_fc, ftr_name)

        with open(output_path, 'w') as file_:
            file_.write('OBJECTID, {}, {}\n'.format(parcel_name, parcel_id))


        with arcpy.da.SearchCursor(fc, (parcel_name, parcel_id), sql_clause=('DISTINCT', None)) as cursor:
            for row in cursor:
                arcpy.AddMessage('Writing information for: {}'.format(row[0]))
                temp_ftr = arcpy.MakeFeatureLayer_management(fc, row[0], "{} = '{}'".format(parcel_name, row[0]), workspace='in_memory')
                selected = arcpy.SelectLayerByLocation_management(building_ftr_local, 'HAVE_THEIR_CENTER_IN', temp_ftr,
                                                                  selection_type='NEW_SELECTION')
                with arcpy.da.SearchCursor(selected, 'OID@') as cur:
                    for r in cur:
                        with open(output_path, 'a') as file_:
                            file_.write("{}, {}, {}\n".format(r[0], row[0], row[1]))
        arcpy.SetParameter(4, output_path)
    except Exception as error:
        arcpy.AddError(error)


if __name__ == '__main__':
    main()
Tags (2)
0 Kudos
5 Replies
DanPatterson_Retired
MVP Emeritus

What are the results?

Is there an error message?

0 Kudos
SuryaKant
New Contributor III

The result is csv file (actual result): OBJECTID, TALUKNAME, TALUKCODE 66641350, Ron, RAUN 78520446, Shahdara, DLHI There is no error as the code runs fine for test (small) database. But it takes too long to execute if I use the main (large) database. So, I was thinking to escape the "arcpy.SelectLayerByLocation_management" tool and get the result.

0 Kudos
DanPatterson_Retired
MVP Emeritus

a spatial join or select by attributes may be appropriate but check the types.  Also a spatial index should be created if it doesn't exist on the input files to speed up any spatial checks.

Also...how slow is slow? seconds? minutes...days?   versus  how many times do you have to do it?

Consider:

  • You can spend as much time, if not more, optimizing code than is actually spent on the use of the function.
  • Working on networks etc will ultimately slow things down and often can't be overcome except by working local.
  • Writing to a file, line by line between operations will be slower than writing stored results all at once.

These should be weighed...

JohnTran1
New Contributor II

I second Dan Patterson A Spatial Join would be the tool you want if you need to see which site points fall "WITHIN" a parcel polygon layer and append their attributes. You can convert the table to a CSV using Table To Table or Excel and CSV Conversion Tools.

0 Kudos
GerryGabrisch
Occasional Contributor III

Can't you accomplish that task using the Spatial Join tool in ArcToolbox, then export the resulting table to a CSV file?

0 Kudos