2

I'm interested in updating a field in geodatabase feature classes based on their location in relation to another feature class in the geodatabase, but without having to perform a join (and therefore creating another feature class).

I've got a polygon feature class ("boundaries") and then multiple point and line features that fall within those boundaries ("fieldData," "streams," "origins"). All of the features, once loaded to the database, have a common field labeled "siteCode" that I would like to populate programmatically rather than manually doing a Select by Location and calculating the fields (or creating extra files like performing a join). Better yet, I would like this to occur as the point and line files are loaded to the geodatabase, but that's not necessary. None of the files have this information stored in their attributes prior to being loaded to the database, but the siteCode is the first two letters in the name of each source shapefile.

As it stands now, I select a feature in the "boundaries" feature class, Select by Location on each of the other files one at a time, and populate the fields using Calculate Field.

I am open to any suggestions for workflow improvement here! My experience is limited with Python but I am interested in learning. If people respond with Python suggestions I would just ask that they include as much information as possible! I feel like this must have been answered a million times but I'm seeing a lot about using a join and not many ways to avoid it.

Also: There is this posting that appears to be accomplishing something similar but I'm too much of a novice to understand exactly what it's doing and if it will do what I need. If someone can confirm that some variation on that code will work for me I will dive in and figure it out!

    #Make a feature layer for the neighourhoods
arcpy.MakeFeatureLayer_management(neighbourhood, "neighbourhoodLayer")
arcpy.MakeFeatureLayer_management(parcel, "parcelLayerTest1")
#Setup cursor to update new NBHD field
with arcpy.da.UpdateCursor(parcel, (parcelIDField,nbhdField)) as parRows:
    for par in parRows:
        # Create a query string for the current patrol zone 
        #parcelIDstring = par[0]
        #queryString = '"' + str(parcelIDField) + '" =' + "'" + str(parcelIDstring) + "'"

        #Select parcels based on location contained within neighbourhood
        arcpy.SelectLayerByLocation_management("parcelLayerTest1", "HAVE_THEIR_CENTER_IN", neighbourhood)

        nbhdTable = arcpy.SearchCursor(neighbourhood)
        for nbhd in nbhdTable:
            nbhdValue = nbhd.getValue("Neighbourh")
            if nbhdValue:
                par[1] = nbhdValue
                parRows.updateRow(par)

Thanks in advance for any assistance.

4
  • 1
    I don't think you are going to be able to avoid doing either selection by location or spatial joining. The post you referenced is using a select by location query. If you are worried about having extra files, you can code in a scratch workspace to store the extra files (in the case of a spatial join) and just clean it up after it is done. Just create a script that does it all and run it every time you import data.
    – Branco
    Jul 24, 2014 at 19:24
  • 3
    Either way I look at the work flow, there needs to be some query or action somewhere that will link the feature classes. ArcMap has to have something telling it that certain features need to relate to others. Spatial joining and select by location are the ways of doing that while preserving the original geometry (unlike operations like Intersect). You could probably do it if you use python to break down the geometries of individual features then query them against each other manually, but since select by location exists, why reinvent the wheel?
    – Branco
    Jul 24, 2014 at 19:28
  • 1
    Exactly Branco, the power of ArcGIS and GIS in general is in spatial relationships; Arc has some powerful tools for determining spatial correlation which I would urge you to use rather than trying to do it all yourself. If you don't want to spatial join how about something like generate near table which you can store in the in memory workspace therefore no extra files and use that to relate records by proximity. Jul 24, 2014 at 21:46
  • Thanks everyone - I wasn't concerned about using a Select by Location as part of a script. I should have clarified - I didn't want to continue doing it manually, one at a time. I also thought there would be a cleaner process than doing a join on the feature class, creating intermediate files AND replacing the original with a new file while maintaining the same name. The answer provided below works quite well and allows me to work within the same file. if anyone sees any issues with this solution please let me know!
    – troubbble
    Jul 28, 2014 at 16:29

1 Answer 1

1

This answer will be similar to the one I gave here...

If I understand your question right, you have parcels (and maybe some other layers) and neighborhoods. You want to calculate a field in the Parcels layer (named SITE_CODE) based on what Neighborhood it's in... if so, try this code...

import arcpy

# Set overwrite option
arcpy.env.overwriteOutput = True

# KEEPING ORIGINAL LAYERS (NOT CREATING ADDITIONAL "JOINED" LAYER)
# Create FeatureLayers
arcpy.MakeFeatureLayer_management("C:/YourFolder/Parcels.shp", "lyr_Parcels")
arcpy.MakeFeatureLayer_management("C:/YourFolder/Neighborhoods.shp", "lyr_Neighborhoods")

# Add an "SIDE_CODE" field   (remove this if the field already exists...)
arcpy.AddField_management("lyr_Parcels", "SITE_CODE", "TEXT", "", "", "20")

# Create a search cursor for the states
rows = arcpy.SearchCursor("lyr_Neighborhoods")
for row in rows:
    # What you'll do is select each neighborhood one at a time, and then select all the parcels in that neighborhood and calculate the SITE_CODE field
    # NOTE: If you are using not using shapefiles, then you'll have to change the FID in the line below to OBJECTID (or similar)
    arcpy.SelectLayerByAttribute_management("lyr_Neighborhoods", "NEW_SELECTION", "\"FID\" = " + str(row.getValue("FID")))
    arcpy.SelectLayerByLocation_management("lyr_Parcels", "INTERSECT", "lyr_Neighborhoods", "", "NEW_SELECTION")
    arcpy.CalculateField_management("lyr_Parcels", "SITE_CODE", "'{0}'".format(str(row.getValue("Neighbourh"))), "PYTHON_9.3", "")
    print "Finished processing " + str(row.getValue("Neighbourh")) 
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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