Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I'm struggling with a python script that is supposed to calculate a field for a polygon feature class. The calculation is of the average of a field value (P_TOT_DEV) for each of a given polygon's neighbors.

The script should:

  1. Make a table of each polygon and it's neighbors
  2. Use that table to get each polygon's neighbor's P_TOT_DEV value
  3. Calculate that to a table called P_TOT_DEV_SUM
  4. Use that table to calc to a table called P_TOT_DEV_AVG
  5. Determine each polygon's average of its neighbor's P_TOT_DEV score
  6. Write that back to the original polygon feature class.

This is not a script I wrote.

Here's the whole script:

# NeighborScore.py
# Created on: 2013-01-07 13:26:35.00000
# Description: Will create output tables based on the average and sum of neighboring polygon values
# Updated 2014-03-10


# Import arcpy module
import arcpy

#   Script arguments
#   This is the table that will be joined to the polygon to create the scoring
#   score_table = arcpy.GetParameterAsText(0)
#   if score_table == '#' or not score_table:
#    score_table = "C:\\Project Work\\Squaxin\\Data Recieved From Squaxin\\SquaxinCat.gdb\\NZ"

#  Join Field for the Score Table and the Polygon Features
searchfield = arcpy.GetParameterAsText(1)
if searchfield == '#' or not searchfield:
    searchfield =  "HydroID"

workspace = "\\\\Fs3\\fs\\Campus Share\\GIS\\Dept\\NR\\Current\\LandscapeAnalysis\\Working.gdb"

#  Polygon Features used in the Neigborhood scoring
polygon_features = arcpy.GetParameterAsText(2)
if polygon_features == '#' or not polygon_features:
    polygon_features = workspace +"\\SSHIAP_Catchment_HARN_1220"

#  Key Field for the Polygon Table to Join to the score table
neighborhoodkeyfield = arcpy.GetParameterAsText(3)
if neighborhoodkeyfield == '#' or not neighborhoodkeyfield:
    neighborhoodkeyfield =  "HydroID"

#   List of fields to be scored (must be numeric)
scorefields = arcpy.GetParameterAsText(4)
if scorefields == '#' or not scorefields:
    scorefields = "P_TOT_DEV"

#   Swap the ; for a , in the delete fields
scorefields = scorefields.split(';')

#   Get the name for the feature class
infeature_name = polygon_features[polygon_features.rindex("\\") + 1:]
print infeature_name

#   inscore_name = score_table[score_table.rindex("\\") + 1:]
#   print inscore_name

#   Set Geoprocessing environments
arcpy.AddMessage("Seting up the input tables")
#   polygon_features[:infeature_name.rindex("\\")]
print workspace
f_layer_out = "flayer"
polygon_neighbors = workspace + "\\PolygonNeighbors"
arcpy.AddMessage(workspace)
arcpy.env.workspace = workspace
arcpy.env.overwriteOutput = True
field = "src_" + searchfield
neighborfield = "nbr_" + searchfield

sum_insert = "P_TOT_DEV_SUM"
avg_insert = "P_TOT_DEV_AVG"

#   Process: Make Feature Layer
arcpy.MakeFeatureLayer_management(polygon_features, f_layer_out, "", "", "")

#   Process: Add Join
#   arcpy.AddMessage("Joining score to neighborhood table")
#   arcpy.AddJoin_management(f_layer_out, neighborhoodkeyfield, score_table, searchfield, "KEEP_COMMON")

#   Process: Create Polygon Neighbors Table
arcpy.AddMessage("Creating Polygon Neighborhood Table")
arcpy.PolygonNeighbors_analysis(f_layer_out, polygon_neighbors, searchfield, "NO_AREA_OVERLAP", "BOTH_SIDES", "", "FEET", "SQUARE_FEET")

#   Process: Copy
arcpy.AddMessage("Copying score tables")
arcpy.Copy_management(polygon_features, avg_insert, "Table")
arcpy.Copy_management(polygon_features, sum_insert, "Table")

#   Process: Delete Rows
arcpy.AddMessage("Cleaning up the score tables")
arcpy.DeleteRows_management(avg_insert)
arcpy.DeleteRows_management(sum_insert)

#   List the Fields for processing
fields = arcpy.ListFields(sum_insert)

#   Determine the Fields to Delete
deletefields = []
for infield in fields:
    if not infield.name.upper() in scorefields and infield.name.upper() <> searchfield.upper():
        print infield.name
        if infield.type == "OID" or infield.name == "Shape" or infield.name == "Shape_Length" or "Shape_Area":
            continue
        else:
            deletefields.append(infield.name)

print deletefields

#   Clean up the extra fields we do not want here
#   arcpy.DeleteField_management(sum_insert, deletefields)
#   arcpy.DeleteField_management(avg_insert, deletefields)

#   Cursor through the neighborhood table
arcpy.AddMessage("Starting the Scoring System")
cursor = arcpy.SearchCursor(polygon_neighbors)
changeid = -99
score = 0
rowcount = 0
average = 0
for row in cursor:
    key_id = row.getValue(field)
    #   shape = row.getValue("SHAPE")
    arcpy.AddMessage("Processing Row....")
    print key_id
    if changeid <> key_id:
        if changeid <> -99:
            try:
                #   Insert the score values
                print score
                insert_cur = arcpy.InsertCursor(sum_insert)
                insert_avg_cur = arcpy.InsertCursor(avg_insert)
                insert_row = insert_cur.newRow()
                insert_avg_row = insert_avg_cur.newRow()
                insert_row.setValue(searchfield,key_id)
                #   insert_row.setValue("SHAPE",shape)
                insert_avg_row.setValue(searchfield,key_id)
                #   insert_avg_row.setValue("SHAPE",shape)
                for key, value in list.iteritems():


                    if key <> searchfield:
                        insert_row.setValue(key.upper(),value)
                        insert_avg_row.setValue(key.upper(),value / rowcount)
                insert_cur.insertRow(insert_row)
                insert_avg_cur.insertRow(insert_avg_row)

                del insert_cur, insert_avg_cur
            except Exception as err:
                print err.message

        #   Track the neighborhood blocks
        changeid = key_id
        score = 0
        rowcount = 0
        list = {}
        for lookfield in scorefields:
            if(lookfield.upper() <> searchfield.upper()):
                list[lookfield.upper()] = 0

    #   Select the appropriate neighborhood fields
    print searchfield + "," + neighborfield
    where = "\"" + searchfield + "\"" + " = "  + str(row.getValue(neighborfield))
    print where
    score_table_search = arcpy.SearchCursor(polygon_features,where)
    for score_table_row in score_table_search:
        for lookfield in scorefields:
            if(lookfield.upper() <> searchfield.upper()):
                list[lookfield.upper()] = list[lookfield.upper()] + score_table_row.getValue(lookfield.upper())
        arcpy.AddMessage(list)
        #  Look through for all the doubles and calculate the scores
        rowcount = rowcount + 1
    del score_table_search 
del cursor

##  Do not delete while testing/review
#   Perform some cleanup
#     if arcpy.Exists(polygon_neighbors):
#   Execute Delete
#   arcpy.Delete_management(polygon_neighbors, "")

The script runs without crashing but, it appears;

  1. the first polygon of the PolygonNeighbors table is not being calculated
  2. fact the that first item/row in the table is not being calculated then throws off all the following calculations. It appears that the calculations (SUM & AVG) are being written to the wrong (+1) polygon. So, poly B is getting poly A's correct results. Poly C is getting B's. Poly A does not make it from the PolygonNeighbors table to the SUM & AVG tables.

The particulars that are confusing me are:

  1. line 44: infeature_name = polygon_features[polygon_features.rindex("\") + 1:] confused as to what infeature_name would be after this (thur each iteration of the loop)
  2. line 90: the delete_fields list appears to be empty Is that right?
share|improve this question
1  
Welcome to GIS SE . Two comments :1) why not use arcpy.PolygonNeighbors_analysis 2) could you please edit your question to make it more readable (in a code block) –  radouxju Mar 11 at 20:31
    
radouxju, Yup, using arcpy.PolygonNeighbors_analysis to produce the PolygonNeighbors table. Issues appear to be after that. Not sure how to ask my question in a code block. I think this is a mid to high level question as it would seem to be more about the logic of the code rather than the code crashing (it does not crash). –  Brian Mar 11 at 20:41
    
radouxju, Any guidance on why my post/question fonts are messed up? Thanks, B –  Brian Mar 11 at 20:44
    
it seems that PolyGeo has done it for you. for the next time, you can press the "edit" button under your post, select all your code and chose "code block" layout. –  radouxju Mar 11 at 21:26
1  
As it stands I think your Question is too broad but it is clear that you have already put some effort into trying to understand why your script is not working so I would like to try and help. It sounds like the Polygon Neighbors tool (step 1) is producing the output that you expect, but I think it would help make your question clear if you included a picture of a few records (just the fields that are relevant) from that. Then it sounds like what you expect to see departs from what you observe in step 2 - so I think this Question should only include the code snippet needed to make that work. –  PolyGeo Jun 22 at 1:58

1 Answer 1

One possible problem is that you use two insert cursors at the same time. If you want to store the sum and the average, you should do this on the same row but in different fields.

Also, I recommend you to use the arcpy.da cursors if you have ArcGIS 10.

share|improve this answer
    
radouxju, Thanks for the cursor wisdom. So, would I want to use the same code block twice beginning at line 105("# Cursor Through the neighborhood table") & ending at line 165 ("del cursor")? In reviewing the tables I do see however that the SUM & AVG calculations are correct - again EXCEPT for the fact that the first polygon is skipped and calculations are in the wrong polygon row... so it doesn't appear to be jamming the logic UNLESS using 2 cursor at the same time would result in the skipping of the first polygon/row. Thanks, B –  Brian Mar 11 at 22:21
    
@Brian I'm not certain but I suspect that I would do this using one Search Cursor and one Update Cursor rather than any Insert Cursors. In any event I think we would be wise to break your script down into more Answer-able chunks to ensure that the Q&As that result are all valuable. –  PolyGeo Jun 22 at 2:02

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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