3

Within a Python script, I would like to replace the geometry of all features in Layer A with the geometry of features in Layer B if their ID fields match.

I am not sure how to do this, but the closest I have gotten (conceptually) is by using updateCursor and the SHAPE@ token. The following code kind of makes sense to me, but is not updating the geometry. Does anyone have any suggestions for fixing this code or another method that would work better?

def burnCPP(sgcn_layer, cpp_layer):

    # create cursors for Layer A and Layer B
    sgcn = arcpy.da.UpdateCursor(sgcn_layer, ["DataSource", "DataID", "SHAPE@"])
    cpp = arcpy.da.SearchCursor(cpp_layer, ["EO_ID", "SHAPE@"])

    # create list and fill with IDs from Layer A
    sgcn_list = []
        if row[0] == "PNHP":
            sgcn_list.append(str(row[1]))

    # create list and fill with matching IDs and geometry of Layer B
    match = []
    if str(row[0]) in sgcn_list:
        match.append([row[0], row[1]])

    # start iteration through rows in Layer A
    with sgcn as cursor:
        for row in cursor:
            # for each row in Layer A, start iteration through each list in match
            for lists in match:
                # if ID in row in Layer A matches ID in list in match fill geometry in Layer A with geometry stored in match list
                if row[1] == lists[0]:
                    row[2] = lists[1]
                    cursor.updateRow(row)

1 Answer 1

6

It looks like you're never actually stepping into your SearchCursor on cpp. It will be more performant if you build a dictionary of cpp_layer first, then use that for the ID lookups.

cpp = {}
with arcpy.da.SearchCursor(cpp_layer, ["EO_ID", "SHAPE@"]) as sCursor:
    for row in sCursor:
        cpp[row[0]] = row[1]

Then in your UpdateCursor you can just test for the id match in cpp.

with arcpy.da.UpdateCursor(sgcn_layer, ["DataSource", "DataID", "SHAPE@"]) as uCursor:
    for row in uCursor:
            # Update the geometry if it's in cpp.
            recordId = row[1]
            if recordId in cpp:
                row[2] = cpp[recordId]
                uCursor.updateRow(row)
6
  • 1
    This should be the accepted answer, using lookup dictionary will be much faster.
    – crmackey
    Sep 2, 2016 at 15:18
  • This makes sense! However, I am getting a StopIteration: iteration not started error on line 12.
    – mmoore
    Sep 2, 2016 at 15:41
  • What code is on line 12?
    – Evan
    Sep 2, 2016 at 15:51
  • cursor.updateRow(row)
    – mmoore
    Sep 2, 2016 at 15:53
  • 1
    Change it to uCursor.updateRow(row). I fixed the code example to reflect this.
    – Evan
    Sep 2, 2016 at 16:03

Your Answer

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

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