1

I am new to using ArcPy/Python and I'm running into problems with a script I'm trying to write.

I'm using IDLE Python 3.6.8 ArcGIS Pro 2.4.0

Here is what I'm trying to do - I have 2 feature classes: 1. Water Mains, 2. Multi Ring buffer.

Within the Water Mains attribute table there is a "CriticalityScore" field. This is an integer value that is assigned based on the diameter(inches) of the pipe. Small diameter pipes = low value, larger diameter pipes receive higher values.

I am tasked with writing a script that will calculate this score for newly added pipes. I created a coded domain for a field called "Participation" to indicated "Yes/No". New pipes that are added into the attribute table by default receive "No."

What I have done so far is to assign if diameter = x then criticality score will = y.

Here's how the scores might look

  1. 2" = (score of) 5
  2. 4" = 9
  3. 10" = 15 etc..

What I'm struggling with now is:

  • Only updating "CriticalityScore" if "Participation" = "No"

Here's what I have so far

#set your workspace, where is this pulling data from? (gdb file path)  
  ws = env.workspace = r"H:\Python Scripts & Tools\Script Tester - Crit Scoring.gdb"

  #set the name of the shapefile path with which you're working (water main .shp)
  fclass = r"H:\Python Scripts & Tools\Script Tester - Crit Scoring.gdb\Water_Mains.shp"

  buffers = r"L:\Engineering\Brice\CriticalityScoringwPipeTestBrice.gdb\BufferParcelEmergancyResponceFac"

  #The third item in "fields" (index position [2])should be the Yes/No field in the feature class
  fields = ["Diameter", "CriticalityScore", "Participation"]


  with arcpy.da.UpdateCursor(fclass, fields) as cursor:
      while row[2] == No:
          for row in cursor:
            if row[0] == 2:
                row[1] = "5"
            elif row[0] == 3:
                row[1] = "7"
            elif row[0] == 4:
                row[1] = "9"
            elif row[0] == 6:
                row[1] = "11"
            elif row[0] == 8:
                row[1] = "13"
            elif row[0] == 10:
                row[1] = "15"
            elif row[0] == 12:
                row[1] = "17"
            elif row[0] == 16:
                row[1] = "20"
            else:
                row[1] = "22"
            cursor.updateRow(row)
          print("The script has finished.")

The script was working before I added the "While row[2] statement. As of right now it will run through the script and give me the ending print statement, but the .aprx/attribute table is never actually updated.

  • 4
    It is not possible to put a shapefile inside a geodatabase (or include a period in an FGDB table name), so by line 5 your script can't work. – Vince Aug 26 at 19:17
2

The first part of you question can be solved with a starting if statement. Or better use a where_clause in the cursor to only iterate over "No" rows. A while loop is not what you want as it will stop iterating when the first "Yes" is encountered.

And instead of multiple if-elif-else you can use a dictionary:

d = {2:"5", 3:"7", ..., 16:"20") #Add all your values.

with arcpy.da.UpdateCursor(fclass, fields) as cursor:
    for row in cursor:
        if row[2] == "No": #You forgot the quotes
            row[1] = d.setdefault([row[0], "22") #Fetch value. If not found use "22")
            cursor.updateRow(row)

For the second part you could try:

  1. Add a field to the buffers with values of 20, 10 and 5
  2. Intersect with points
  3. Dissolve by point id and sum on value field
  4. Join the results back to the original points
  5. Include the joined field in your logic
  • 2
    The nesting if can be eliminated by a where_clause of "{:s} = 'No'".format(fields[2]) – Vince Aug 26 at 17:50
  • @Vince, could you help me understand what the {:s} is doing? When I try this, it runs through the script w/o error, but does not update my attribute table. – brice.f Aug 26 at 18:49
  • 2
    Make sure Diameter is a double or integer field (and not string) otherwise something like if row[0] == 2 will never be true, but this will if row[0] == '2' and the same logic goes for the dictionary. Also check data type of CriticalityScore as it will need to be a string to set value to for example "5" otherwise it should be 5 – BERA Aug 26 at 18:53
  • 1
    The joy of using a where_clause is that you can print it out to look at what is being processed. {:s} formats a string parameter to the string.format() function. – Vince Aug 26 at 19:18
  • 2
    Also, the lovely dict.setdefault property can eliminate else bit, e.g., row[1] = d.setdefault(row[0], "22") – fatih_dur Aug 27 at 0:04
1

This ended up working for me. Used both answers to help me finish. I removed the ".shp" from my file paths and that began to update the attribute table. I still don't understand the where clause so I think I'll have to read up on that and know how it works before I implement it.

  ws = env.workspace = r"H:\Python Scripts & Tools\Script Tester - Crit Scoring.gdb"
  #set the name of the shapefile path with which you're working (water main .shp)
  fclass = r"H:\Python Scripts & Tools\Script Tester - Crit Scoring.gdb\Water_Mains"
  #The third item in "fields" (index position [2])should be the Yes/No field in the feature class
  fields = ["Diameter", "CriticalityScore", "Participation"]
  d = {2:"5", 3:"7", 4:"9", 6:"11", 8:"13", 10:"15", 12:"17", 16:"20",}
  with arcpy.da.UpdateCursor(fclass, fields) as cursor:
    for row in cursor:
        if row[2] == "No": 
            if row[0] in d: #If row[0] is in dictionary keys
                row[1] = d[row[0]] #Fetch value
            else:
                row[1] = "22"
            cursor.updateRow(row)
    print("The script has finished.")``` 
  • 1
    This "{:s} = 'No'".format(fields[2]) is another way of writing "Participation = 'No'" and can be used as a where clause in the cursor to iterate over only those rows: with arcpy.da.UpdateCursor(fclass, fields, "Participation = 'No'") ... – BERA Aug 27 at 5:14

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.