for row1 in rows1: count = 1 print "row %d" %parcelrow parcelrow = parcelrow +1 selectcount = 0 currentPIN = row1.getValue(selectField) arcpy.SelectLayerByAttribute_management(mapLyr1, "NEW_SELECTION", "\"%s\" = '%s'" %(selectField, currentPIN)) print currentPIN arcpy.SelectLayerByAttribute_management(mapLyr2, "ADD_TO_SELECTION", "\"%s\" = '%s'" %(selectField, currentPIN)) selectcount = int(arcpy.GetCount_management(mapLyr2).getOutput(0)) print "%d points selected" %selectcount if selectcount == 0: arcpy.SelectLayerByAttribute_management(mapLyr1, "CLEAR_SELECTION") pass else: for row2 in rows2: hydrantfield = copytoField + "%d" %count print "filling field " + hydrantfield hydrID = row2.getValue(copyField) #This setValue is supposed to update mayLyr1 row1.setValue(hydrantfield, hydrID) rows1.updateRow(row1) count = count + 1 arcpy.SelectLayerByAttribute_management(mapLyr1, "CLEAR_SELECTION") arcpy.SelectLayerByAttribute_management(mapLyr2, "CLEAR_SELECTION")
I have a script that uses one layer to select features of a second layer in the first loop of the script. When the second layer's features are selected, I have a second loop that is supposed to update the fields on the first layer in the first loop. Is there a specific way of using an updateCursor or setValue to affect the nesting loop?for row1 in rows1: count = 1 print "row %d" %parcelrow parcelrow = parcelrow +1 selectcount = 0 currentPIN = row1.getValue(selectField) arcpy.SelectLayerByAttribute_management(mapLyr1, "NEW_SELECTION", "\"%s\" = '%s'" %(selectField, currentPIN)) print currentPIN arcpy.SelectLayerByAttribute_management(mapLyr2, "ADD_TO_SELECTION", "\"%s\" = '%s'" %(selectField, currentPIN)) selectcount = int(arcpy.GetCount_management(mapLyr2).getOutput(0)) print "%d points selected" %selectcount if selectcount == 0: arcpy.SelectLayerByAttribute_management(mapLyr1, "CLEAR_SELECTION") pass else: for row2 in rows2: hydrantfield = copytoField + "%d" %count print "filling field " + hydrantfield hydrID = row2.getValue(copyField) #This setValue is supposed to update mayLyr1 row1.setValue(hydrantfield, hydrID) rows1.updateRow(row1) count = count + 1 arcpy.SelectLayerByAttribute_management(mapLyr1, "CLEAR_SELECTION") arcpy.SelectLayerByAttribute_management(mapLyr2, "CLEAR_SELECTION")
The second loop seems to get stuck. Shouldn't the loop only run through the selected features then continue back to the first loop?
import arcpy, os, time #set map doc and the layer to be used mxd = arcpy.mapping.MapDocument("Current") mapLyr1 = arcpy.mapping.ListLayers(mxd, "Parcels_With_PageNum") [0] mapLyr2 = arcpy.mapping.ListLayers(mxd, "H2O_Pts_Nearest_Address2") [0] ID_Silvis = int() rows1 = arcpy.UpdateCursor(mapLyr1, "", "", "NEW_PIN") for row in rows1: hydcount = 1 newpin = row.NEW_PIN print newpin arcpy.SelectLayerByAttribute_management(mapLyr2, "NEW_SELECTION", " \"NEW_PIN\" = '%s' " %newpin) rows2 = arcpy.UpdateCursor(mapLyr2) for row2 in rows2: hydfield = "Hydr_Num" + str(hydcount) hydID = ID_Silvis row.setValue(hydfield, hydID) rows1.updateRow(row) hydcount = hydcount + 1 arcpy.SelectLayerByAttribute_management(mapLyr2, "CLEAR_SELECTION") del mxd, row, rows1, row2, rows2, mapLyr1, mapLyr2, hydcount, hydfield, hydID
Thank you for that. I kind of restarted what I had yesterday, and I'll past the whole thing this time. I understand the posts I've quickly looked at in that link and will give that consideration when I rework this again. For now this is what I have. And just our of curiousity, I already know you don't recommend the old cursors (read that part) can a nested loop update or set a value to a layer outside of itself? In other words, can "row2" update a field in "row1?"import arcpy, os, time #set map doc and the layer to be used mxd = arcpy.mapping.MapDocument("Current") mapLyr1 = arcpy.mapping.ListLayers(mxd, "Parcels_With_PageNum") [0] mapLyr2 = arcpy.mapping.ListLayers(mxd, "H2O_Pts_Nearest_Address2") [0] ID_Silvis = int() rows1 = arcpy.UpdateCursor(mapLyr1, "", "", "NEW_PIN") for row in rows1: hydcount = 1 newpin = row.NEW_PIN print newpin arcpy.SelectLayerByAttribute_management(mapLyr2, "NEW_SELECTION", " \"NEW_PIN\" = '%s' " %newpin) rows2 = arcpy.UpdateCursor(mapLyr2) for row2 in rows2: hydfield = "Hydr_Num" + str(hydcount) hydID = ID_Silvis row.setValue(hydfield, hydID) rows1.updateRow(row) hydcount = hydcount + 1 arcpy.SelectLayerByAttribute_management(mapLyr2, "CLEAR_SELECTION") del mxd, row, rows1, row2, rows2, mapLyr1, mapLyr2, hydcount, hydfield, hydID
I know this code is considered slow, but from what I've learned of Python so far, it's the best I know how to do. But I will read through the page you linked. Thank you.
import arcpy, os, time #set map doc and the layer to be used mxd = arcpy.mapping.MapDocument("Current") mapLyr1 = arcpy.mapping.ListLayers(mxd, "Parcels_With_PageNum") [0] mapLyr2 = arcpy.mapping.ListLayers(mxd, "H2O_Pts_Nearest_Address2") [0] ID_Silvis = int() rows1 = arcpy.UpdateCursor(mapLyr1, "", "", "NEW_PIN") for row in rows1: hydcount = 1 newpin = row.NEW_PIN print newpin arcpy.SelectLayerByAttribute_management(mapLyr2, "NEW_SELECTION", " \"NEW_PIN\" = '%s' " %newpin) rows2 = arcpy.UpdateCursor(mapLyr2) for row2 in rows2: hydfield = "Hydr_Num" + str(hydcount) hydID = row2.GetValue("ID_Silvis") # or whatever field that holds the row2 ID row.setValue(hydfield, hydID) hydcount = hydcount + 1 arcpy.SelectLayerByAttribute_management(mapLyr2, "CLEAR_SELECTION") rows1.updateRow(row) del row2, rows2 del mxd, row, rows1, mapLyr1, mapLyr2, hydcount, hydfield, hydID
import arcpy #set map doc and the layer to be used mxd = arcpy.mapping.MapDocument("Current") mapLyr1 = arcpy.mapping.ListLayers(mxd, "Parcels_With_PageNum") [0] mapLyr2 = arcpy.mapping.ListLayers(mxd, "H2O_Pts_Nearest_Address") [0] ID_Silvis = int() rows1 = arcpy.UpdateCursor(mapLyr1, "", "", "NEW_PIN") for row in rows1: hydcount = 1 newpin = row.NEW_PIN print newpin arcpy.SelectLayerByAttribute_management(mapLyr2, "NEW_SELECTION", "\"NEW_PIN\" = '%s'" %newpin) rows2 = arcpy.UpdateCursor(mapLyr2) for row2 in rows2: hydfield = "Hydr_Num" + str(hydcount) ID_Silvis = row2.ID_Silvis # arcpy.CalculateField_management(mapLyr1, hydfield, hydID, "PYTHON") row.setValue(hydfield, ID_Silvis) hydcount = hydcount + 1 rows1.updateRow(row) # arcpy.SelectLayerByAttribute_management(mapLyr2, "CLEAR_SELECTION") del mxd, row, rows1, mapLyr1, mapLyr2, hydcount, hydfield, hydID, row2, rows2
Thank you for your help Richard. You're right about ID_Silvis. Between revisions that got mixed up. ID_Silvis is the field I need copied. So I went and corrected that and on a single feature with 2 points it seems to be working. The next thing, would be to create a selection of features to run the script on. So right now I have about 340 points, but when I do a join, they only seem to be associated with 90 parcels. So to create a definition query that could select just those 90 parcels and run the script on those instead of 3,500 parcels. I will be reading into how to create a list and using that to create a selection. So far here's what I've got working.
import arcpy #set map doc and the layer to be used mxd = arcpy.mapping.MapDocument("Current") mapLyr1 = arcpy.mapping.ListLayers(mxd, "Parcels_With_PageNum") [0] mapLyr2 = arcpy.mapping.ListLayers(mxd, "H2O_Pts_Nearest_Address") [0] ID_Silvis = int() # uncomment the next line if you want to be sure all points affect the parcels selected # arcpy.SelectLayerByAttribute_management(mapLyr2, "CLEAR_SELECTION") arcpy.SelectLayerByLocation_management(mapLyr1, 'intersect', mapLyr2) # add every Hydr_Num field name to list rows1 = arcpy.UpdateCursor(mapLyr1, "", "", "NEW_PIN; Hydr_Num1; Hydr_Num2; Hydr_Num3; Hydr_Num4") for row in rows1: hydcount = 1 newpin = row.NEW_PIN print newpin arcpy.SelectLayerByAttribute_management(mapLyr2, "NEW_SELECTION", "\"NEW_PIN\" = '%s'" %newpin) rows2 = arcpy.SearchCursor(mapLyr2, "", "", "ID_Silvis") for row2 in rows2: hydfield = "Hydr_Num" + str(hydcount) ID_Silvis = row2.ID_Silvis # arcpy.CalculateField_management(mapLyr1, hydfield, hydID, "PYTHON") row.setValue(hydfield, ID_Silvis) hydcount = hydcount + 1 rows1.updateRow(row) del row2, rows2 # arcpy.SelectLayerByAttribute_management(mapLyr2, "CLEAR_SELECTION") del mxd, row, rows1, mapLyr1, mapLyr2, hydcount, hydfield, hydID
Since there aren't too many points to parcels in the data, I was able to sort the attribute table of the points and see what the max number of hydrants per parcel there was and so I created 6 or 7 "hydr_x" fields. The counter starts at one and can fill up to that point. You're right about what if I run out of fields, though. Then the counter resets back to 1 at the beginning of the first loop. I tried adding the del row2, rows2 to the end of the first loop, but I get an error saying row2, rows2 isn't defined.
For a selection, I was thinking about creating a list of all unique values in the point layer and using that as a definition query. Not all the points are contained within a parcel. But I did use a spatial join of "nearest neighbor" to get a PIN for each point. So select by location wouldn't return all the parcels that need to be selected.
import arcpy #set map doc and the layer to be used mxd = arcpy.mapping.MapDocument("Current") mapLyr1 = arcpy.mapping.ListLayers(mxd, "Parcels_With_PageNum") [0] mapLyr2 = arcpy.mapping.ListLayers(mxd, "H2O_Pts_Nearest_Address") [0] ID_Silvis = int() field = 'NEW_PIN' fcName = 'H2O_Pts_Nearest_Address' myList = set([row.getValue(field) for row in arcpy.SearchCursor(fcName)]) field = 'NEW_PIN' dquery = [] for mapLyr2 in arcpy.mapping.ListLayers(mxd, fcName): for row in arcpy.SearchCursor(mapLyr2): dquery.append("'{}'".format(row.NEW_PIN)) mapLyr1.definitionQuery = '"NEW_PIN" in ({})'.format(", ".join(dquery)) rows1 = arcpy.UpdateCursor(mapLyr1, "", "", "NEW_PIN") for row in rows1: hydcount = 1 newpin = row.NEW_PIN print newpin arcpy.SelectLayerByAttribute_management(mapLyr2, "NEW_SELECTION", "\"NEW_PIN\" = '%s'" %newpin) rows2 = arcpy.SearchCursor(mapLyr2) for row2 in rows2: hydfield = "Hydr_Num" + str(hydcount) ID_Silvis = row2.ID_Silvis # arcpy.CalculateField_management(mapLyr1, hydfield, hydID, "PYTHON") row.setValue(hydfield, ID_Silvis) hydcount = hydcount + 1 rows1.updateRow(row) arcpy.SelectLayerByAttribute_management(mapLyr2, "CLEAR_SELECTION") mapLyr1.definitionQuery = '' del mxd, row, rows1, mapLyr1, mapLyr2, hydcount, hydfield, row2, rows2, dbquery, field, myList, fcName, field#, hydID