1

I am currently trying to generate an ID based on two conditions but I am having troubles to achieve that since I am failing to make my script work. Below the explanation and my code, I apologies if there an outrageous mistake I couldn't pick up but at this stage I am genuinely stuck and I still consider myself a newbie in arcpy and python.

The conditions for Tsec to change is: row1 has to be equal 2 and row[0] has to be != previous, at the same time I need to keep those values in the index that do not meet the conditions within the same id. The ID continues incrementing on an on and there freq change from 1 to 2 and 2 to 1, in the same structure of the table in the image.

Attribute table representing the ID sequence, in green is what I have and in red is what I need to achieve

Below is the code I am trying to use to achieve that:

import arcpy
# Set parameter to export feature class
in_fc = arcpy.GetParameterAsText(0)
out_fc = arcpy.GetParameterAsText(1)
# Set variables
previous = 1
rec = 1
# Start the loop to update the row according to the conditions required
with arcpy.da.UpdateCursor(in_fc,['NewID','Freq', "Tsec"]) as cursor:
     for row in cursor:
     previous = row[0]
         while row[2] == 2:
            if row[0] != previous:
               row[2] = rec + 1
            else:
                if row[0] == previous:
                   row[0] = rec
         while row[2] == 1:
            if row[0] != previous:
               row[2] = rec
            else:
                if row[0] == previous:
                   row[2] = rec
                   break
                   cursor.updateRow(row)
 arcpy.CopyRows_management(in_fc, out_fc)
2
  • 3
    This is more of a Python coding 101 issue, starting with an invalid indent scheme. You can do this manually with selection and Calculate Field without learning Python.
    – Vince
    Commented Aug 11, 2022 at 0:52
  • I thought it would be a Python 101 coding issue, thanks for poiting that out. It will be great to be able to get a little bit more of guidance since I am trying to do a scrip embedded into the model builder so manual selections are not needed. Probably my bad for not characterizing my goal properly.
    – cerroGIS
    Commented Aug 11, 2022 at 1:57

3 Answers 3

4

If I understand your logic correctly the field calculator expression:

remA = 1;remB = 1
def getTSEC(V,TRIGGER):
 global remA,remB
 if remA!=V and TRIGGER==2:  remB+=1
 remA = V
 return remB
'---------------
getTSEC( !NewID!, !FREQ!)

Should suffice:

enter image description here

1
  • 1
    Yes it actually worked!, thank you so much!
    – cerroGIS
    Commented Aug 11, 2022 at 4:32
2

Your code has a lot of random looping that serves no clear purpose.

The core issue is that you have no clear algorithm for assigning the contents of Tsec. It's trivially easy to populate based on the on the rule you've demonstrated:

import arcpy

# Set parameter to export feature class
in_fc = arcpy.GetParameterAsText(0)
out_fc = arcpy.GetParameterAsText(1)   # Unused

# Set variable

lookup = {
     1  : 1,
     2  : 1,
     3  : 1,
     4  : 2,
     5  : 2,
     6  : 2,
     7  : 2,
     8  : 2,
     9  : 3,
    10  : 3,
    11  : 3,
}

# Start the loop to update the row according to the conditions required
with arcpy.da.UpdateCursor(in_fc,['NewID','Freq', "Tsec"]) as cursor:
    for row in cursor:
        row[2] = lookup[row[0]]
        cursor.updateRow(row)

But this doesn't really do any good, because the population of the lookup dictionary is human-generated.

For the record:

  • The indent scheme of Python is the only way to manage flow of control. Your code would generate errors at previous = row[0] because the for loop has no contents. It would fail again at the ifs after else and at arcpy.CopyRows_management(in_fc, out_fc) for indent misalignment. Please do not post code that generates syntax errors in GIS SE.
  • You can use any indent scheme you want, so long as you only want four spaces (this is the standard for having your code usable by others, and for using others code as well -- see PEP8).
  • Even if you fixed the indentation, the break assures that the cursor update would never occur
  • While I have used while a couple of times in the past decade, it does NOT belong in this code. If you're going to write Python code, you need remedial study in how to use for (and if-elif and break and lists and dictionaries).
  • I break out in hives if I try to use CopyRows, so I left that part out.
5
  • Thank you soooo much!. I will correct the code from the original post with the correct indentation asap. Then will try your approach and then hopefully share it with everyone in case I solve it. I would love to keep learning and improving and certainly this is a lot of help. Thanks again:).
    – cerroGIS
    Commented Aug 11, 2022 at 3:12
  • Since I couldn't find a proper way to put the code in a proper way I decided just to erase it and leave the question as it is. Thank you so much again for the effort to pointing out the mistakes and give me advise.
    – cerroGIS
    Commented Aug 17, 2022 at 21:11
  • 1
    Defacing your post isn't the best way to handle this. The code you provided cannot execute, so it's less about "proper way" and more about "representative code block". Not having any code at all is worse than having bad code, so I've rolled back the edit, but you really need to learn how to to use Python if you intend to make a career of GIS (at this point, it's indispensable)
    – Vince
    Commented Aug 17, 2022 at 23:06
  • I did noticed. Will work harder to correct it! sorry about that.
    – cerroGIS
    Commented Aug 17, 2022 at 23:09
  • I think I found the way to do it, although with my skills I think for sure should be a easier way to do it. Anyway, thank you so much for the challenge!.
    – cerroGIS
    Commented Aug 18, 2022 at 4:14
0

I think this is the answer to what I asked above, for sure there must be a better and more simple way to achieve it. Using cursors in ArcPy.

import arcpy
# Set Parameter to export table
in_table = arcpy.GetParameterAsText(0)
out_table = arcpy.GetParameterAsText(1)
#Read through fields
field1 = [row[0] for row in arcpy.da.SearchCursor(in_table, ["NewID"])]
field2 = [row[0] for row in arcpy.da.SearchCursor(in_table, ["Freq"])]
#set counter and index
counter = 1
index = -1
#Use cursor to update value
with arcpy.da.UpdateCursor(in_table,["Tsec"]) as cursor:
    for row in cursor:        
        if index<=len(field1)-2:
            n0 = field1[index]
            n1 = field1[index+1]
            n2 = field2[index]
            n3 = field2[index+1]            
            if n1 > n0 and n3 == n2 and n3 == 2:
                counter += 1
                row[0] = counter
            else:
                False
            cursor.updateRow([counter])
            index+=1
        else:
            cursor.updateRow([counter])
            break
arcpy.CopyRows_management(in_table, out_table)

This is the result

enter image description here

2
  • 1
    You still have invalid indentation. Use four space for each indent. That's the rule. Just put a triple-backtic above and below your working code. Your code makes unreasonable assumptions about row order -- guaranteed that this wouldn't work in an enterprise geodatabase. You only need one updateRow. The else: False serves no purpose. And the break logic is bizarre.
    – Vince
    Commented Aug 18, 2022 at 4:21
  • I would love to hear more about the unreasonable assumptions... just to keep learning (baby steps :D) and I would love to see the code optimized, then again to keep learning :
    – cerroGIS
    Commented Aug 18, 2022 at 4:31

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.