This post could easily be called "How I fell in love with dictionaries"
Drawing the idea from this post http://forums.arcgis.com/threads/525...ctor-one-liner
I've come up with a solution to a nagging problem I know I have been having, and I believe some others have as well, of not being able to reliably use an update cursor when dealing with joined tables. I was really happy with my first foray into dictionaries, and I thought I'd share my work around for anyone looking to optimize some tedious processing with joins. My data was ~900k rows of forest stand data in one table, and a strata reference table of ~50 rows to calculate volumes. My previous method of using a permanent JoinField, processing, then deleting those fields, took approximately 3.5 hours. Temporary joins never worked for me in the manner I needed. Using dictionaries instead of joins, that time was reduced to under 15 minutes.
This code goes through any table and creates a list of field names for every field other than OID and the key field you want to reference.
Here is the fairly complete code to create the dictionary
In the update cursor you can then either explicitly reference dictionary objects like thisCode:print "Starting function" # Define and setup variables, tables, key field etc calc_table = arcpy.MakeTableView_management(table_path) vol_tab = join_table_path strata_tab = "in_memory/temp" arcpy.MakeTableView_management(vol_tab, strata_tab) joinField = "STRATA" # Create list of value fields, leaving out OID field and key/join field flistObj = arcpy.ListFields(strata_tab) flist = [] for f in flistObj: if f.type != "OID" and f.name != joinField: flist.append(f.name) # Create empty dict object then populate each key with a sub dict by row using value fields as keys strataDict = {} for r in arcpy.SearchCursor(strata_tab): fieldvaldict = {} for field in flist: fieldvaldict[field] = r.getValue(field) strataDict[r.getValue(joinField)] = fieldvaldict del strata_tab, flistObj
What I did was use a reference list to reference the dictionary to keep things legible, and so I could remember what went where. This may not even be necessary for some people, but it helped me conceptually. Without getting in to too much detail, here's essentially my update cursor sans the actual calculations.Code:rows = arcpy.UpdateCursor(calc_table, "\"%s\" IS NOT NULL" % joinField) for row in rows: strata = row.getValue(joinField) variable = strataDict[strata]["sub_key_field"]
Hopefully that didn't get too convoluted, anyone else have anything that might contribute in terms of optimization?Code:species = [ ("C","Fb","FB_STEMS"),("C","Sw","SW_STEMS"),("C","Pj","PJ_STEMS"), # 0,1,2 ("C","Pl","PJ_STEMS"),("C","Lt","LT_STEMS"),("C","Sb","SB_STEMS"), # 3,4,5 ("D","Bw","BW_STEMS"),("D","Aw","AW_STEMS"),("D","Pb","PB_STEMS") # 6,7,8 ] sp_fields = [("SP1","SP1_PER"),("SP2","SP2_PER"),("SP3","SP3_PER"), ("SP4","SP4_PER"),("SP5","SP5_PER")] print "Beginning updates" rows = arcpy.UpdateCursor(calc_table, "\"%s\" IS NOT NULL" % joinField) for row in rows: strata = row.getValue(joinField) for sp, per in sp_fields: sp_type = row.getValue(sp) spp_f = float(row.getValue(per)) if spp_f > 0: for grp, spec, stem in species: stem_f = strataDict[strata][stem] (...)



Reply With Quote


Bookmarks