Using dictionary and cursors to calculate a field based on values from another table - KeyError [0]

804
2
06-06-2017 09:20 AM
TessOldemeyer
Occasional Contributor

I'm new to dictionaries and am still a Python beginner. I'm trying to update field(s) based off of field values in another table using the OID field as a key. The search cursor dictionary has been filtered down (in an effort to conditionally update the values in the Line_Count_13_8 field) with a where clause for the portion of the script where I am receiving an error. I am getting a KeyError: [0] error on this line:

if search_feats_138[0] == upd_row[0]: ‍‍

Here is the whole block:

import arcpy
from arcpy import env
import time
start = time.time()
print start
print "Start"
arcpy.env.OverwriteOutput = True

subLayer='C:\Topo_Check_Tess_V5.gdb\Sub'
transLayer='C:\Topo_Check_Tess_V5.gdb\TL'
ppLayer='C:\Topo_Check_Tess_V5.gdb\PP'

pp_trans_GUJoin ='C:\Topo_Check_Tess_V5.gdb\pp_trans_GU_SpatialJoin'

SubLayer_pp_trans_GUJoin = 'C:\Topo_Check_Tess_V5.gdb\SubLayer_pp_trans_GUSpatialJoin'

arcpy.SpatialJoin_analysis ("SubLayer_Layer", "pp_trans_GUJoin_Layer", SubLayer_pp_trans_GUJoin, 'JOIN_ONE_TO_ONE', 'KEEP_ALL', fieldMappings, 'WITHIN_A_DISTANCE', .000002) ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 This section works:

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

search_feats = {f[0]:f[1] for f in arcpy.da.SearchCursor(SubLayer_pp_trans_GUJoin,["OBJECTID","Join_Count"])}

with arcpy.da.UpdateCursor(subLayer,["OBJECTID","Line_Count"]) as upd_cur:
    for upd_row in upd_cur:
        upd_row[1] = search_feats[upd_row[0]]
        upd_cur.updateRow(upd_row)
    print "Line_Counts Updated"
del upd_cur‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

This section does not work - KeyError: [0] on line 13:

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

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

#arcpy.MakeFeatureLayer_management(SubLayer_pp_trans_GUJoin, "Sub_PP_Trans_Join_13_8", where_13_8)

search_feats_13_8 = {f[0]:f[1] for f in arcpy.da.SearchCursor(SubLayer_pp_trans_GUJoin,["OBJECTID","Join_Count"], where_13_8)}

with arcpy.da.UpdateCursor(subLayer,["OBJECTID","Line_Count_13_8"]) as upd_cur:
    for upd_row in upd_cur:
        if search_feats_13_8[0] == upd_row[0]:
            upd_row[1] = search_feats_13_8[upd_row[0]]
        else: 
            upd_row[1] = 0
        upd_cur.updateRow(upd_row)    
    print "Line_Count_13.8 Updated"
del upd_curl

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

Any suggestions? Thanks in advance!

0 Kudos
2 Replies
JoshuaBixby
MVP Esteemed Contributor

I think you want line 13 to be:

if search_feats_13_8.get(upd_row[0], None) == upd_row[0]:‍‍‍

Without using a defaultdict, the problem you will have comparing keys is the error that will be generated when a key isn't present.  Using the .get() method and a default value gets around this problem.  Overall though, I am a fan of using defaultdict.

TessOldemeyer
Occasional Contributor

Thanks! This totally helps. The following ended up doing the trick and replaces lines 13-16.

upd_row[1] = search_feats_13_8.get(upd_row[0], 0)
0 Kudos