Select to view content in your preferred language

Update a feature class based on another table

4311
2
02-10-2014 10:24 AM
TimBash
New Contributor
Hello All:
I am a newbie in python and working on a script that is supposed to update a feature class (fc) based on another table (Table1) by comparing/matching the records in the feature class (fc) to the table (Table1) based on a field "INCIDENT_ID." If there is a match it then updates the feature class(fc) based on the match from the table(not sure if that makes sense). Else: the unmatched records from the table (Table1) are new, so it takes these new records, performs a geocode which should also add XY fields and a spatialjoin of the geocode result with 3 polygon feature classes (ccd, ced, scd) and updates the necessary fields(ccd_name, ccd_desc, ced_name, ced_desc , scd_name and scd_desc) in the feature class(fc) based on the spatialjoin. So far, I have not been able to get the script to run and produce the desired output. And will gladly appreciate any help I can get to stir me in the right direction. I have also attached the script and the sample data I am working with.

#Import system modules
import arcpy
import os
from arcpy import env

#Set environment
env.workspace = r"C:\Users\tim.bash\Documents\ArcGIS\test.gdb"

#Allow overwrite
arcpy.env.overwriteOutput = True

#Define table and features
Table = r"C:\Users\tim.bash\Documents\ArcGIS\test.gdb\Table1"
fClass = r"C:\Users\tim.bash\Documents\ArcGIS\test.gdb\TestData\fc"
ccd = r"C:\Users\tim.bash\Documents\ArcGIS\test.gdb\TestData\ccd" #polygon feature class
ced = r"C:\Users\tim.bash\Documents\ArcGIS\test.gdb\TestData\ced" #polygon feature class
scd = r"C:\Users\tim.bash\Documents\ArcGIS\test.gdb\TestData\scd" #polygon feature class



# fields from the table that should  match the fClass
fieldTable = "INCIDENT_ID"
fieldFclass = "INCIDENT_ID"

# Create cursors
cur = arcpy.UpdateCursor(fClass)
row = cur.Next()

while row:
 #Get the values in fieldTable from field "INCIDENT_ID"
 fieldFclassID = row.GetValue("INCIDENT_ID")
 
 cur2 = arcpy.SearchCursor(Table)
 row2 = cur2.Next()
 
 while row:
 
  #Get the values in the fieldTable from field "INCIDENT_ID"
  fieldTableID = row2.GetValue("INCIDENT_ID")
  
  #If there is a match
  if fieldFclassID == fieldTableID:
  
   fClass = row2.GetValue(fieldTable)
   row.SetValue(fieldFclass, fClass)
   cur.UpdateRow(row)
   print "Updated: ", fclass
   
   #Exit out of loop if match is found
   break
  row2 = cur2.Next()
 
 row = cur.Next()

#if match is not found, proceed to geocode
address_table = "Table"
address_locator = r"C:\Users\tim.bash\Documents\ArcGIS\test.gdb\Addresses_Zip_Locator"
geocode_result = "geocode_result"

#Add XY fields to the geocode_result and calculate XY
sr = arcpy.SpatialReference(3032)

with arcpy.da.UpdateCursor(geocode_result, ["SHAPE@XY", "X", "Y"], "", sr) as cursor:
 for row in cursor:
     row[1] = row[0][0]
     row[2] = row[0][1]
     cursor.updateRow(row)

del row, cursor


##Proceed to spatialjoin geocode_result with ccd, ced and scd

#create a polylayer
polylayers = [ccdlayer, cedlayer, scdlayer]

#make a feature layer for each polygon feature class
try:
     arcpy.MakeFeatureLayer_management(ccd, ccdlayer)
     arcpy.MakeFeatureLayer_management(ced, cedlayer)
     arcpy.MakeFeatureLayer_management(scd, scdlayer)
except:
    arcpy.GetMessages()


# create an update cursor for the spatialjoin process
rows = arcpy.UpdateCursor(geocode_result)

for row in rows:
    rowshape = row.Shape
    for layer in polylayers:
        try:
            arcpy.SelectLayerByLocation_management(layer, "WITHIN", rowshape, "", "NEW_SELECTION")
            count = int(arcpy.GetCount_management(layer).getOutput(0))
        except:
            arcpy.GetMessages()
        
        if count > 0:
            rowslayer = arcpy.SearchCursor(layer)

            for rowlayer in rowslayer:
  if layer == ccdlayer:
     row.ccd_name = str(int(rowlayer.CNCLDIST02))
     row.ccd_desc = rowlayer.DistrictMembers
  if layer == cedlayer:
     row.ced_name = str(rowlayer.SECTION_ID)
     row.ced_desc = str(rowlayer.SECTION_ID)  
  if layer == scdlayer:
     row.scd_name = str(int(rowlayer.SUPER))
     row.scd_desc = str(rowlayer.DistrictMembers)

rows.updateRow(row)

#Delete cursor and row objects to remove locks on the data
del row
del rows
Tags (2)
0 Kudos
2 Replies
JakeSkinner
Esri Esteemed Contributor
If there is a match it then updates the feature class(fc) based on the match from the table(not sure if that makes sense).

You can accomplish by simply Joining the table to the feature class using the 'Add Join' function.  Next, run the 'Calculate Field' function to update the required fields.

Else: the unmatched records from the table (Table1) are new, so it takes these new records

You can get the unmatched records by comparing a list of Incident IDs from the feature class and table, and then selecting the incidents that are unmatched.  Ex:

fc = "fc"
table = "table1"

fcIncident = []
tableIncident = []

with arcpy.da.SearchCursor(fc, ["INCIDENT_ID"]) as cursor:
    for row in cursor:
        fcIncident.append(row[0])

del row, cursor

with arcpy.da.SearchCursor(table, ["INCIDENT_ID"]) as cursor:
    for row in cursor:
        if not row[0] in fcIncident:
            tableIncident.append(row[0])

del row, cursor

arcpy.MakeTableView_management(table, "tblView")

for ID in tableIncident:
    arcpy.SelectLayerByAttribute_management("tblView", "ADD_TO_SELECTION", "INCIDENT_ID = " + str(ID))


which should also add XY fields and a spatialjoin of the geocode result  with 3 polygon feature classes (ccd, ced, scd) and updates the necessary  fields(ccd_name, ccd_desc, ced_name, ced_desc , scd_name and scd_desc)  in the feature class(fc) based on the spatialjoin

You can now geocode the "tblView", create the Spatial Join, and update the required fields:

arcpy.GeocodeAddresses_geocoding("tblView", .....)
FCs = [ccd, ced, scd]
for fc1 in FCs:
    arcpy.SpatialJoin_analysis(fc1, geocodeResult, fc1 + "_join")
    arcpy.MakeFeatureLayer_management(fc, "fcLyr")
    arcpy.MakeFeatureLayer_management(fc1, "fc1Lyr")
    arcpy.AddJoin_management("fcLyr", "INCIDENT_ID", "fc1Lyr", "INCIDENT_ID", "KEEP_COMMON")
    arcpy.CalculateField_management("fcLyr", "fc.ccd_name", ....)
    arcpy.CalculateField_management("fcLyr", "fc.ccd_desc", ....)
    ....


Note:  the field name will change when a join is present.  The field name will begin with the feature class/table name.  i.e. "parcels.ccd_name"
0 Kudos
TimBash
New Contributor
Thanks, I am still getting an AttributeError (AttributeError: 'Cursor' object has no attribute). Also will the arcpy.da.SearchCursor function work in the 10 environment?

If there is a match it then updates the feature class(fc) based on the match from the table(not sure if that makes sense).

You can accomplish by simply Joining the table to the feature class using the 'Add Join' function.  Next, run the 'Calculate Field' function to update the required fields.

Else: the unmatched records from the table (Table1) are new, so it takes these new records

You can get the unmatched records by comparing a list of Incident IDs from the feature class and table, and then selecting the incidents that are unmatched.  Ex:

fc = "fc"
table = "table1"

fcIncident = []
tableIncident = []

with arcpy.da.SearchCursor(fc, ["INCIDENT_ID"]) as cursor:
    for row in cursor:
        fcIncident.append(row[0])

del row, cursor

with arcpy.da.SearchCursor(table, ["INCIDENT_ID"]) as cursor:
    for row in cursor:
        if not row[0] in fcIncident:
            tableIncident.append(row[0])

del row, cursor

arcpy.MakeTableView_management(table, "tblView")

for ID in tableIncident:
    arcpy.SelectLayerByAttribute_management("tblView", "ADD_TO_SELECTION", "INCIDENT_ID = " + str(ID))


which should also add XY fields and a spatialjoin of the geocode result  with 3 polygon feature classes (ccd, ced, scd) and updates the necessary  fields(ccd_name, ccd_desc, ced_name, ced_desc , scd_name and scd_desc)  in the feature class(fc) based on the spatialjoin

You can now geocode the "tblView", create the Spatial Join, and update the required fields:

arcpy.GeocodeAddresses_geocoding("tblView", .....)
FCs = [ccd, ced, scd]
for fc1 in FCs:
    arcpy.SpatialJoin_analysis(fc1, geocodeResult, fc1 + "_join")
    arcpy.MakeFeatureLayer_management(fc, "fcLyr")
    arcpy.MakeFeatureLayer_management(fc1, "fc1Lyr")
    arcpy.AddJoin_management("fcLyr", "INCIDENT_ID", "fc1Lyr", "INCIDENT_ID", "KEEP_COMMON")
    arcpy.CalculateField_management("fcLyr", "fc.ccd_name", ....)
    arcpy.CalculateField_management("fcLyr", "fc.ccd_desc", ....)
    ....


Note:  the field name will change when a join is present.  The field name will begin with the feature class/table name.  i.e. "parcels.ccd_name"
0 Kudos