3

I have a Python Toolbox and want to use the zonal statistics as table function on user-provided polygon shapefiles/feature classes that may or may not have multiple parts.

In the code, I add a new field to the user-provided polygon and create the zones (code below is abbreviated with only pertinent parts):

polygon = parameters[0].value
arcpy.AddField_management(polygon, "Zone", "TEXT", "", "", 15)

EDIT 1: (code immediately below)

d=arcpy.Describe(polygon)
if d.dataType == 'FeatureLayer': 
     polygon = d.featureClass.catalogPath 

Then using field calculator, I create sequential zone numbers:

expression = "autoIncrement(!FID!)"
codeblock = """def autoIncrement(fid):
    fid = int(fid)
    fid += 1
    return "Polygon " + str(fid)"""
arcpy.CalculateField_management(polygon, "Zone", expression, "PYTHON", codeblock)

When I try the tool, the CalculateField_management function stalls and I receive "Error 000728: Field "Zone" does not exist within table". However, opening up the shapefile used to test the tool does reveal that a new field called "Zone", string datatype and length of 15 has been created.

When I refresh the Python toolbox and rerun the tool, this time it runs correctly populating the rows ("Polygon 1", "Polygon 2", ...) and the ZonalStatisticsAsTable function is able to run.

I found a previous post on this issue: Why am I getting an ERROR 000728: Field *fieldname* does not exist within table even though field exists?

Attempted Workarounds:

(1) Instead of using arcpy.CalculateField_management, I tried using an update cursor.

arcpy.AddField_management(polygon, "Zone", "TEXT", "", "", 15)
start = 1
cursor = arcpy.da.UpdateCursor(polygon, "Zone")
for row in cursor:
   row[0] = "Polygon " + str(start)
   start = start + 1
cursor.updateRow(row)
del row, cursor  


arcpy.sa.ZonalStatisticsAsTable(polygon, "Zone", ...)   [code goes on]

Instead of the previous error, the code stalls on the ZonalStatisticsAsTable function instead and I receive "Error 001000: Field "Zone" does not exist". As before, checking the shapefile's attribute table reveals that the "Zone" field exists as it should after arcpy.AddField_management function.

(2) Use "FID" as zones to avoid having to use arcpy.AddField_management and arcpy.sa.ZonalStatisticsAsTable in succession.

Tool does now run without either errors, yet summary statistics are incorrect. Basically it looks like values of "MIN", "MAX", and "MEAN" have been shifted over, so this doesn't look like a viable option.

My thoughts: Is there some kind of lock preventing the code from running top to bottom? Issue occurs after I add the new field and then want to do something to that field. It's weird that I need to rerun the code twice in order to not receive errors. Since I hope to have this tool available for other users, this isn't acceptable.

  • 1
    Are you running this on a layer or a feature class? Note that Zone isn't used in autoIncrement so is not required as a parameter. – Michael Stimson Apr 17 '17 at 22:52
  • @MichaelMiles-Stimson Appreciate the response. I guess I want flexibility to run it on either. When I remove Zone as a parameter from autoIncrement, I have the same issue (2 runs to avoid the error). – Edward Apr 17 '17 at 22:59
  • 1
    Layers have field definitions, feature classes do not. If you've switched off some fields the new field may not be visible, thereby usable, in the layer. Try use d=arcpy.Describe(polygon), if d.dataType == 'FeatureLayer': polygon = d.featureClass.catalogPath to turn a layer into a feature class. If you're running this in ArcMap make sure that you're not editing as that will lock the table and might refuse to add a new field depending on the storage type of the feature class and version of ArcGIS. – Michael Stimson Apr 17 '17 at 23:06
  • It could be your field name, see gis.stackexchange.com/questions/123736/… and docs.microsoft.com/en-us/sql/t-sql/language-elements/… which states that Zone is a SQL keyword, try using a non-reserved keyword like 'aZone' or 'Zon'. – Michael Stimson Apr 17 '17 at 23:19
  • 1
    No, that's right. Try replacing the data source after adding the field arcpy.MakeFeatureLayer_management(polygon,'polygonLayer') Lay=arcpy.mapping.Layer('polygonLayer') then Lay.replaceDataSource(os.path.dirname(polygon),'SHAPEFILE_WORKSPACE') to see if that refreshes.. note that creating a Layer object doesn't work from a feature class only from a layer already. – Michael Stimson Apr 18 '17 at 0:41
2

Creating a layer after AddField_management, saving a copy of it, and then manipulating the copy got me around Error 000728, which stemmed from a "refresh" issue.

polygon = parameters[0].value
output_folder = parameters[1].valueAsText

# Add unique field to perform zonal stats
arcpy.AddField_management(polygon, "Zone", "", "", 15)

# Work-around to Error 000728 --- subsequent code points to new shapefile
arcpy.MakeFeatureLayer_management(polygon, 'polygonLayer')
arcpy.CopyFeatures_management('polygonLayer', output_folder + "\\" + "Treatment_Zones.shp")
refresh_poly = output_folder + "\\" + "Treatment_Zones.shp"

# Expression to populate new "Zone" field
expression = "autoIncrement(!FID!)"
codeblock = """def autoIncrement(fid):
    fid = int(fid)
    fid += 1
    return "Polygon " + str(fid)"""

arcpy.CalculateField_management(refresh_poly, "Zone", expression, "PYTHON", codeblock)

# Calculate Zonal Statistics
arcpy.sa.ZonalStatisticsAsTable(refresh_poly, "Zone", .....)  [code goes on]

Might not be the most elegant solution, but I'm relieved that this now works satisfactorily.

0

I ran into something similar. There is a 'refresh' problem when working with layers or feature class objects in arcpy. The workaround is pretty simple-- input the datasource path to CalculateField, not the python object.

i.e.

polygon = parameters[0].value
# If the input is a layer, get the data source path
desc = arcpy.Describe(polygon)
if hasattr(desc, "layer"):
    polygon_path = desc.dataElement.catalogPath
else:  # assume param is the full path to a feature class 
    polygon_path = arcpy.GetParameterAsText(0)

arcpy.AddField_management(polygon_path, etc....)
arcpy.CalculateField(polygon_path, etc...)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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