Python: retrieving from list & adding autoincrement IDs

2715
14
07-14-2014 08:27 AM
HayleySmall
New Contributor II

Hi all,

I was wondering if you could help me write a script for Field Calculator.

I have a list of 2,000+ entries contained in about 40 parks. Each park has a field ParkID which is already filled out. I'd like to create a script that generates UniqueIDs based on the ParkIDs.

Ex. ParkID = Q001

.:. UniqueIDs = Q001_001, Q001_002, all the way to Q001_100 or however many necessary depending on how many entries, but then beginning at 001 again when reaching a new park, i.e. R142_001, R142_002, etc.

I want to first retrieve each ParkID from the list of ParkIDs and then use that list to create an autoincrement starting at 001 for each unique ParkID.

I'd rather do this that just do an autoincrement for each park individually.

I have very little python experience and might not quite understand some details, so could you please explain in depth?


EDIT:
Right now I have the following script in the Codeback of Field Calculator:

rec=0

plot = ""

def autoIncrement(park):

global rec

global plot

pStart = 1 

pInterval = 1

if (rec == 0): 

  rec = pStart 

  plot = park

  plot = plot + "_000"+ str(rec)

  rec += pInterval

elif (rec < 10): 

   plot = park + "_000" + str(rec)

   rec += pInterval  

elif (rec > 9 and rec < 100): 

   plot = park + "_00" + str(rec)

   rec += pInterval 

elif (rec > 99 and rec < 1000): 

  plot = park + "_0" + str(rec)

  rec += pInterval

else:

   plot = park +  "_" + str(rec)

   rec += pInterval 

return plot

And the following in the "FIELD_NAME" = autoIncremet(!ParkID!)

This code works, but starts the unique ID at 0 and goes up into the thousands. I am trying to find a way to make it so for each new ParkID, the unique ID restarts at 001 again.

Best,

Hayley

Message was edited by: Hayley Small

14 Replies
WesGoldstein
Occasional Contributor III

Hi Hayley Small‌,

   I moved your post to the Python‌ space where it should get better attention. There are many places in GeoNet which you can SEARCH for or just BROWSE

0 Kudos
ToddUlery
Occasional Contributor

Hi Hayley,

Can I ask if the 2000 + Park data have ParkID = Q '' only? or is it a mix?

Just need to know whether to account for different ParkID's in that field or if one park is only 'Q' another park is another 'P' for example?

Just want to make sure I understand it fully.

Thanks

Todd

0 Kudos
HayleySmall
New Contributor II


Hi Todd

The parks are either "QXXX" (i.e. Q001), "XXXX" (i.e. X092), RXXX (i.e. R142), BXXX (i.e. B057), or MXXX (i.e. M321)

Thanks.

0 Kudos
HayleySmall
New Contributor II

Additionally, all Park IDs are already entered into a field "ParkID", so it would just be ParkID_001 for each new park

0 Kudos
ToddUlery
Occasional Contributor

Hayley,

Steps to complete:

  1. Right click the field that will be update
  2. Open up the Field Calculator; either save the attachment file and load it in the calculator or copy the Pre-Logic Script Code in the corresponding section after you check the box for Show CodeBlock in the Calculator and also Add the following to the Seciont Below the Pre-Logic Section:
    • UniqueID( !ParkID! )

Field Calculator:

Parser: Python

Fields: [YOUR FIELD THAT UPDATES]

Pre-Logic Script Code:

s1 = " "

def UniqueID(ParkID):

  global s1, count

  y = ParkID

  s = str(y)

  s = s[0]

  if s != s1:

    count = 1

  else:

    count += 1

  pad = str(count).zfill(3)

  z = ParkID + '_' + pad

  s1 = s

  return z

Whats going on above:

s1 = " " Empty String Variable that will update to hold the Value from the Field

def UniqueID(ParkID):  Defined Function the holds the meat and potatoes

  global s1, count Global Variables for transfer of values in and out of function(Local)

  y = ParkID Variable set to hold the value of the ParkID Field

  s = str(y) Converting the ParkID Field Value to a string Value

  s = s[0] Taking the First index of the string value (the letter of the field value)

  if s != s1: A if conditional that reads the string value(letter) and compares it to the empty string from earlier

    count = 1 count within the first conditional

  else: Else Conditional

    count += 1 count within the second conditional

  pad = str(count).zfill(3) Variable that pads zero's on to the current count (3 zero's)

  z = ParkID + '_' + pad  Variable that hold a concatenated string value of both the original Field Value from ParkID and added on "_" incremental count.

  s1 = s ‌After the first run of the function on the first row it will set the empty variable to the field value for the conditionals, this will alow for the count to continue to add + 1

  return z Returns the value to add to table

If this doesn't work please include the error in the results.
Thanks

Todd

HayleySmall
New Contributor II

Thanks for your help, Todd. Unfortunately it did not work. Here are the error results:

Errors.JPG

0 Kudos
HayleySmall
New Contributor II

Now that I look more closely, I am actually getting a really bizarre output. It seems like some of the Unique IDs are being generated, but some of the are repeating, or restarting again at _001 at random times. Not sure why this would happen. Additionally, some of the Unique IDs are not being generated at all. I'm not sure if they just had not been gotten to before the failure occurred and the values there are leftover from my other trials, or if they are generating just strange numbers in the thousands.

Here are some random snippets/examples:

Ex1.JPGEx2.JPGEx3.JPG

Ex. 1 shows random numbers in the thousands in the same park as where _001 starts randomly two times.

Ex. 2 shows a park that goes from _001 immediately to _062

Ex. 3 shows a park that goes from _030 to a random numbers, and then a new park begins randomly at _033, and then a new park begins with random numbers.

Hayley

0 Kudos
ToddUlery
Occasional Contributor

That does look a little strange. The above error is probably because of null values. In order to have to incremental numbering we needed to access the first index in the range of characters for the string (DATA VALUE). If the data is NULL it cant access that, and will say it is out of range and fail.  I would personally run a script on something like this. It allows for better access to the data. May not have the random that seems to occur. I don't know the quality of the data; i.e. what type of abnormalities to account for.

0 Kudos
HayleySmall
New Contributor II


Todd,

It actually seems like it has to do with the ObjectIDs. It seems to start over or mess up wherever the objectIDs are not perfectly ascending. For example, some data may have been collected over a large period of time, with other parks' data in between, so the object IDs are chunks at a time. IDs  1-200 and then 2300-2450 might belong to one park,, because other parks' info was taken in between (200-2300). I'm not sure if there is a way around this- incrementing based on *not* the objectIDs, but I used the script that I wrote ^above^ and just executed it individually for each park (i.e. 40+ times), which was not ideal, but worked.

0 Kudos