I've added a new field "CatchAreaKm2" (Double) to a File Geodatabase Table. I then create a list of fields of the table that will be used in an UpdateCursor. The problem that I have is that the newly added field is listed within the list of fields yet when I iterate through a sliced version of the fields (landuse) it doesn't recognize the newly added "CatchAreaKm2" field and I can't understand for the life of me why not. In order the get a list of the Landuse fields the index slice should be row[1:-1] yet if I use the following it skips the last landuse field ignoring the newly added field. in order to get the following to work I need to using the index slice row[1:]
Any help solving why the newly field is not being recognized will be appreciated.
Python: landuse_fields
# calculate percentage of landuse per watershed def landuse_percentage(watershed, output_pivot): watershed_fields = ["HydroID", "Shape_Area"] valuedict = {r[0]: (r[1:]) for r in arcpy.da.SearchCursor(watershed, watershed_fields)} # @UndefinedVariable arcpy.AddField_management(output_pivot, "CatchAreaKm2", "DOUBLE") landuse_fields = [f.name for f in arcpy.ListFields(output_pivot)[1:]] print(landuse_fields) with arcpy.da.UpdateCursor(output_pivot, landuse_fields) as upcur: # @UndefinedVariable for row in upcur: keyvalue = row[0] if keyvalue in valuedict: arcpy.AddMessage("Processing Watershed {0}".format(keyvalue)) # add catchment area km² to newly added field row[-1] = valuedict[keyvalue][0]/1000000 for i, landuse in enumerate(row[1:]): # index slice not picking up newly added field row = (row*(28*28))/(valuedict[keyvalue][0])*100 upcur.updateRow(row) landuse_percentage(watershed, output_pivot)
Python: Code (Currently working)
# calculate percentage of landuse per watershed def landuse_percentage(watershed, output_pivot): watershed_fields = ["HydroID", "Shape_Area"] valuedict = {r[0]: (r[1:]) for r in arcpy.da.SearchCursor(watershed, watershed_fields)} # @UndefinedVariable arcpy.AddField_management(output_pivot, "CatchAreaKm2", "DOUBLE") landuse_fields = [f.name for f in arcpy.ListFields(output_pivot)[1:]] print(landuse_fields) with arcpy.da.UpdateCursor(output_pivot, landuse_fields) as upcur: # @UndefinedVariable for row in upcur: keyvalue = row[0] if keyvalue in valuedict: arcpy.AddMessage("Processing Watershed {0}".format(keyvalue)) # add catchment area km² to newly added field row[-1] = valuedict[keyvalue][0]/1000000 for i, landuse in enumerate(row[1:-1]): # index slice should be row = (row*(28*28))/(valuedict[keyvalue][0])*100 upcur.updateRow(row) landuse_percentage(watershed, output_pivot)
Python: Code (Not working)
Solved! Go to Solution.
Hi All
I solved it, I was correct that the index slice should be row[1:-1] what I had missed that the index starts at 0 and can be managed with an optional argument within Python Enumerate Function.
# calculate percentage of landuse per watershed def landuse_percentage(watershed, output_pivot): watershed_fields = ["HydroID", "Shape_Area"] valuedict = {r[0]: (r[1:]) for r in arcpy.da.SearchCursor(watershed, watershed_fields)} # @UndefinedVariable arcpy.AddField_management(output_pivot, "CatchAreaKm2", "DOUBLE") landuse_fields = [f.name for f in arcpy.ListFields(output_pivot)[1:]] with arcpy.da.UpdateCursor(output_pivot, landuse_fields) as upcur: # @UndefinedVariable for row in upcur: keyvalue = row[0] if keyvalue in valuedict: arcpy.AddMessage("Processing Watershed {0}".format(keyvalue)) row[-1] = valuedict[keyvalue][0]/1000000 for i, landuse in enumerate(row[1:-1], 1): row = (landuse*(28*28))/(valuedict[keyvalue][0])*100 print("Index: {0}, Landuse: {1}, CatchAreaKm2: {2}, Percentage: {3}".format(i, landuse, row[-1], row)) upcur.updateRow(row) landuse_percentage(watershed, output_pivot)
Thanks for all the help, from everyone.
Sorry Peter,
What do you mean "doesn't recognize the newly added".
Has the AddField worked or not?
What error do you get if you access the field?
Hi Neil
The field is added and identified within the list, yet when I step into line 15 I should have to adjust the index slice row[1:] to row[1:-1] to exclude the added field from fields being updated.
Hi Dan Dan Patterson \ Luke Luke Pinner
Just wonder if either of you have any idea why my enumerate function isn't working as expected. The index slice should be row[1:-1] yet it doesn't work, only row[1:] works, which shouldn't as it would include the newly added "CatchAreaKm2" field.
Slicing
>>> flds = [u'HydroID', u'Commercial_Forestry',...snip.., u'Urban', u'Waterbodies', u'Wetlands', u'CatchAreaKm2'] >>> flds[1:] ['Commercial_Forestry', ... snip..., 'Urban', 'Waterbodies', 'Wetlands', 'CatchAreaKm2'] >>> flds[1:-1] ['Commercial_Forestry', 'Cultivated', ...snip... 'Urban', 'Waterbodies', 'Wetlands'] >>> >>> flds[:-1] ['HydroID', 'Commercial_Forestry', ... snip..., 'Urban', 'Waterbodies', 'Wetlands']
lst, 1: slice from index 1 to end
2nd slice from 1 to everything except the last
3rd slice from the start (index 0) except the last.
I am not quite sure why you need an enumerator... I will have to think... I tend not to use iterators, generators etc, but either to use the built-in array operations or variants of list comprehensions (ie set, dictionary comps) Do be aware that numpy has builtin iterators and generators which work best with arrays more so that their pure python equivalents. Something else to write about now that I have thrown it out
Hi Dan
Thanks for getting back to me. The reason for using the enumerator was to be able to update a specific list of fields within the UpdateCursor using the same formula without having to specify each index position (i.e. row[1], row[2]) etc. I solved the following by using the optional argument to specify the starting index number. The original post is under the following discusssion:
Hi All
I solved it, I was correct that the index slice should be row[1:-1] what I had missed that the index starts at 0 and can be managed with an optional argument within Python Enumerate Function.
# calculate percentage of landuse per watershed def landuse_percentage(watershed, output_pivot): watershed_fields = ["HydroID", "Shape_Area"] valuedict = {r[0]: (r[1:]) for r in arcpy.da.SearchCursor(watershed, watershed_fields)} # @UndefinedVariable arcpy.AddField_management(output_pivot, "CatchAreaKm2", "DOUBLE") landuse_fields = [f.name for f in arcpy.ListFields(output_pivot)[1:]] with arcpy.da.UpdateCursor(output_pivot, landuse_fields) as upcur: # @UndefinedVariable for row in upcur: keyvalue = row[0] if keyvalue in valuedict: arcpy.AddMessage("Processing Watershed {0}".format(keyvalue)) row[-1] = valuedict[keyvalue][0]/1000000 for i, landuse in enumerate(row[1:-1], 1): row = (landuse*(28*28))/(valuedict[keyvalue][0])*100 print("Index: {0}, Landuse: {1}, CatchAreaKm2: {2}, Percentage: {3}".format(i, landuse, row[-1], row)) upcur.updateRow(row) landuse_percentage(watershed, output_pivot)
Thanks for all the help, from everyone.
Your enumerate 'i' still starts at 0, even though the list you're enumerating starts at 1.
>>> my_fields = [u'HydroID', u'Commercial_Forestry', u'Cultivated', u'Indigenous', u'Mines', u'Natural_Vegetation_Forest', u'Urban', u'Waterbodies', u'Wetlands', u'CatchAreaKm2'] ... for i, landuse in enumerate(my_fields[1:]): ... print (i,my_fields) ... (0, u'HydroID') (1, u'Commercial_Forestry') (2, u'Cultivated') (3, u'Indigenous') (4, u'Mines') (5, u'Natural_Vegetation_Forest') (6, u'Urban') (7, u'Waterbodies') (8, u'Wetlands') >>> my_fields = [u'HydroID', u'Commercial_Forestry', u'Cultivated', u'Indigenous', u'Mines', u'Natural_Vegetation_Forest', u'Urban', u'Waterbodies', u'Wetlands', u'CatchAreaKm2'] ... for i, landuse in enumerate(my_fields[1:-1]): ... print (i,my_fields) ... (0, u'HydroID') (1, u'Commercial_Forestry') (2, u'Cultivated') (3, u'Indigenous') (4, u'Mines') (5, u'Natural_Vegetation_Forest') (6, u'Urban') (7, u'Waterbodies')
Hi Darren
I was busy posting my answer to my own question, when your reply came through. By specifying the starting number of the index I was able to solve it. Thanks for your reply.
Sorry Peter, that was my bad, I missed the fact you were slicing your row list to start from the 2nd element. I've updated my answer in your other post - https://community.esri.com/message/620711#comment-620711