Auto Increment by Attribute

2735
4
05-31-2018 03:24 PM
MTCGIS
by
New Contributor II

Hello, 

I'm trying to create a function that leverages the auto increment function which is provided as a field calculator example in ArcGIS Pro's Calculate Field Python examples. The auto increment function is pretty straight-forward however, I'm looking to increment based on the attributes of another field. I've attached an example of the desired output. Below I've provided a snippet of the code where I've attempted to create a function that does what I've described but it doesn't seem to be working and I'm probably missing some important information about how field calculator works with tables. In the autoincrement function, you set the initial value to 0. But in an attempt to keep my function generic, I want to set the initial value to whatever is passed in when the function is called, then keep comparing.

new = ''
def autoIncrementbyAttr(attribute):
    global new
    exist = attribute
    if (exist == new):
        return autoIncrement()
    else:
        new = attribute
        rec=0

rec=0
def autoIncrement():
global rec
pStart = 1 #adjust start value, if req'd  
pInterval = 1 #adjust interval value, if req'd
if (rec == 0):  
  rec = pStart  
else:  
  rec = rec + pInterval  
return rec‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
4 Replies
DarrenWiens2
MVP Honored Contributor

This type of problem, where you need to keep track of key/value pairs (county/map #), is best organized in a dictionary, where for each key (county) you increment the value (map #). See: 5. Data Structures — Python 2.7.15 documentation 

Here's an example, not using the field calculator (sorry). In the field calculator, counter_dict should be global, and instead of appending to output_list, you'd return the value counter_dict[county]:

county_list =
['Marin',
'Napa',
'Napa',
'Marin',
'Marin',
'Napa',
'Marin',
'Marin',
'Napa',
'Napa',
'Napa',
'Napa',
'Marin',
'Napa',
'Marin',
'Napa',
'Marin',
'Marin',
'Napa',
'Marin']

counter_dict = {}
output_list = []

for county in county_list:
    counter_dict[county] = counter_dict.get(county, 0) + 1
    output_list.append([county, counter_dict[county]])

output_list =
[['Marin', 1],
['Napa', 1],
['Napa', 2],
['Marin', 2],
['Marin', 3],
['Napa', 3],
['Marin', 4],
['Marin', 5],
['Napa', 4],
['Napa', 5],
['Napa', 6],
['Napa', 7],
['Marin', 6],
['Napa', 8],
['Marin', 7],
['Napa', 9],
['Marin', 8],
['Marin', 9],
['Napa', 10],
['Marin', 10]]
DanPatterson_Retired
MVP Esteemed Contributor

You can use the following field calculator expression.

A demo using a list is given in the example and a screen shot of it in an actual field calculation is given

d = ['a', 'b', 'a', 'a', 'c', 'd', 'b', 'a', 'b', 'd']

"""
Count the number of 'val's that exist in a field and number and format
them, incrementing the number each time one is found
"""

kv = {}  # empty dictionary
cnt = 0
def key_count(val):
    global kv
    #global cnt
    if val not in kv.keys():
        cnt = 0
        kv[val] = 0
        ret = "{}_{:03.0f}".format(val, cnt)
    else:
        cnt = kv[val] + 1
        kv[val] = cnt
        ret = "{}_{:03.0f}".format(val, cnt)
    return ret



for i in d:
    print(key_count(i))
   
a_000
b_000
a_001
a_002
c_000
d_000
b_001
a_003
b_002
d_001‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

0 Kudos
DanPatterson_Retired
MVP Esteemed Contributor

Attached is the field calculator expression that you can load *.cal file

It was tested in ArcGIS Pro, but hopefully should work in a python 2.7 environment

Of course... you will have to modify to suit your needs.. and if you have fewer than 1000's of records, then you can easily change the padding format from

ret = "{}_{:03.0f}".format(val, cnt)‍‍‍  # padding for 1000's‍‍ of records duplicate
ret = "{}_{:02.0f}".format(val, cnt)‍‍‍  # padding for 100's‍‍
ret = "{}_{:01.0f}".format(val, cnt)‍‍‍  # padding for a few.... get the drift???
DanPatterson_Retired
MVP Esteemed Contributor

Functionality added to Table Tools for PRO should you move forward with Pro.

The functionality is essentially the same, but use numpy to vectorize the calculations.

0 Kudos