1

I have two landcover classifications (as shapefiles) created using eCognition. "Level0 (FID)" consist of larger polygons and "Level1 (FID, ClassName, Area_Pxl)" of smaller polygons within these. I would prefer a solution using arcpy but other solutions will also do (R, geopandas). Script is preferred since I need to repeat this many times.

I will describe my current workflow here emphasizing what is missing:

  1. Create a new column Level0_ID to Level1
    • Done
  2. Extract ID from Level0
    • I need to extract the ID of that segment in Level0 to Level1_ID column when Level0 polygon contains Level1 polygon. What tool should I use?
  3. Create new field agric_perc to Level0
    • Done
  4. I need to create a loop that goes through the attribute table and does the following function:
    • If Level0_ID (in Level1) == ID (in Level0) Then agric_perc (Level0) is agri_perc + Area_Pxl (in Level1)

I think this should do the trick but I am having trouble formulating the script and finding the right tools. I know there is a solution for this where the Level1 shapefile is converted to raster, but I have very large dataset (millions of segments) and original pixel size is very small so the raster solution is very slow and would rather keep the classifications as shapefiles.


What I was thinking looks something like this, but maybe there is better solution:

import arcpy
from arcpy import env
import os
import sys

# Set workspace
arcpy.env.workspace = "C:\HY-Data\RPIIROIN\documents\Rami_opetus\eCognitionWorkshop\DevelopingMethods\PolyPerc"

#Create datareader
Cursor1 = arcpy.UpdateCursor("Level1.dbf")

#Create column Level0_ID to Level1
arcpy.AddField_management(Level1, "Level0_ID", "SHORT", 5, "", "", "Classified", "NULLABLE", "REQUIRED")

#Extract ID from Level0
- How to do this?

#Create column agric_perc to Level0
arcpy.AddField_management(Level0, "agric_perc", "SHORT", 5, "", "", "Classified", "NULLABLE", "REQUIRED")

#Create the loop to update agric_perc column
- How do I create a loop that sums the Level0_ID values from Level1 to Level0 agric_perc column

Added a picture of the overlapping shapefiles and the attribute tables

3
  • Your agric_perc value should not be updated each time you look at a Level1 polygon, but rather all at once at the end (store the areas in a variable as you are looping through, then use that variable later with an UpdateCursor). I don't have much time at the moment to look at a detailed solution, but hopefully this suggestion either points you in the right direction or somebody else can flesh it out :)
    – Erica
    Mar 10, 2015 at 16:53
  • Are all the Level 1 polygons contained wholly by a Level 0 polygon, or do some overlap multiple Level 0 polygons?
    – Erica
    Mar 10, 2015 at 16:54
  • Are you able to join the data either with a spatial join or based on a common field? If so you could easily select the records and calculate the field value. Mar 10, 2015 at 18:53

1 Answer 1

1

Performing selections of feature layers within an update cursor is how I would accomplish this task. Create your feature layers, and then iterate through your features with an update cursor. Select each Level0 feature with an sql where clause. Perform a select by location to determine which Level1 features are within the selected Level0 feature. Perform a field calculate the Level1 feature layer with the OID. Then use a search cursor on your selected Level1 features to sum your areas. Update your row object after performing the needed math. Something like this will do, if you are using ArcGIS 10.1 or beyond...

#Create feature layers to allow selection
arcpy.MakeFeatureLayer_management (Level0, "lyr0")
arcpy.MakeFeatureLayer_management (Level1, "lyr1")

#Get layer OBJECTID field
OIDfld = arcpy.Describe ("lyr0").OIDFieldName

#Iterate through Level0 feature layer
with arcpy.da.UpdateCursor ("lyr0", ["OID@", "agric_perc", "SHAPE@AREA"]) as cursor:
    for row in cursor:

        #sql to select individual feature in Level0 feature class
        sql = '{0} = {1}'.format (arcpy.AddFieldDelimiters ("lyr0", OIDfld), row[0])

        #Select feature in Level0 feature class
        arcpy.SelectLayerByAttribute_management ("lyr0", "", sql)

        #Select intersecting Level1 features
        #Choose selection type to suit (INTERSECT, WITHIN, etc)
        arcpy.SelectLayerByLocation_management ("lyr1", "WITHIN", "lyr0")

        #Check for selection
        if arcpy.Describe ("lyr1").FIDSet:

            #Update selected features in Level1 with Level0 OID
            arcpy.CalculateField_management ("lyr1", "Level0_ID", row[0])

            #Sum areas with list comprehension and searchcursor
            AllAreas = sum([r[0] for r in arcpy.da.SearchCursor ("lyr1", "SHAPE@AREA")])
            #Do math (percent as whole number)
            AreaPercent = AllAreas / row[2] * 100

            #Update percent field
            row[1] = AreaPercent

            #Update row
            cursor.updateRow(row)

If you are using a version of ArcGIS before 10.1, look into the older version of the UpdateCursor. I hope this helps!

3
  • Thanks! This looks very promising and I will test it as soon as possible. I will tell how it went then!
    – RaimoIII
    Mar 11, 2015 at 11:35
  • I tried your script but I could not get it to work yet. I added also a picture of the data and the two attribute tables. So I need for example the percentage of Level1 "Agriculture" classes within each Level0 segment. I think an additional selection is needed for Level1 class at some point and the sum (area) of these within Level0 divided by given Level0 segment area is then updated for each Level0 segment. I hope i'm being clear and thousand thanks for your help. It got me started well!
    – RaimoIII
    Mar 11, 2015 at 16:42
  • Btw I'm sorry I cannot yet upvote your answer since it requires 15 reputation points :/
    – RaimoIII
    Mar 11, 2015 at 17:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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