Iterative position within Field Calculator/Python

I'm not great with Python or programming in general, so I'm not even sure how to ask this question.

Basically what I've got is in the left column, and what I want is in the right column.

``````UniqueID    POSITION
a              1
a              2
a              3
a              4
a              5
b              1
c              1
c              2
d              1
e              1
``````

I guess what I need to do is loop through the sorted UniqueID field and increment the Position field UNTIL the UniqueID changes, in which case the Position should reset to 1.

NFI how to make this actually work. I've done a lot of searching and have found some promising-looking code, but I just don't have the know-how to make it fit my problem. Sorry about my brain. My script right now looks like "Baby's first adventures with arcpy," and since this is slightly more complicated than a simple arcpy call, it's stopped me in my tracks.

I guess I'm looking for something that works as part of a CalculateField operation?

-
Is the order within each category important? What are you sorting on currently? – Stev_k Apr 3 '12 at 8:33
– om_henners Apr 3 '12 at 11:50
That's not a duplicate question, @om, but its solution can be exploited to answer this question. (Assign unique ids in sort order; summarize by [UniqueID] to obtain minimum id per key value; join the summary back; subtract the minimum (and add one) to get the desired result.) – whuber Apr 3 '12 at 16:31
@whuber Fair call - my misreading of the question. If there's a way to remove the close vote I will. – om_henners Apr 3 '12 at 22:35
It's ok, @om: close votes will automatically go away in a few days. (I have no way to remove them either...) – whuber Apr 4 '12 at 12:44

Cursors are your friend. You want to use the update cursor. The documentation explains it pretty well, but essentially, the cursor returns a set of rows that you can loop through. The update cursor allows you to edit the data. You can also sort your result.

I can think of three very simple approaches all of which will do what you want:

1. As you suggest
2. Make a list of the UniqueID values (e.g. ```uniqueID_list = ['a', 'b', 'c', 'd']```) and loop over this list using the current value in the where_clause of the cursor to preselect a given 'UniqueID' and then iterate the returned rows in a nested loop. This is a good approach if the position value is dependent on some other attribute because you can use the 'sort' clause of the currsor.
3. Make an empty dictionary (`uniqe_dict = {}`). Get all rows using an update cursor and start looping over them. For each row test the value of uniqueId against the dictionary. If it exists in the dictionary, add one to the dictionary value. If the uniqueId is not in the dictionary add it as a new key to your dictionary with a value of 1. Now update the 'position' field with the dictionary value of the current uniqueId key.

Any of these approaches will work. The 3rd one sounds more complicated than it is but does not reuire that you find out what all your uniqueIds are beforehand and saves the nested loops of approach #2 (if some other order is important you can still pre-sort on the third field beforehand).

There is a fourth approach that requires no coding at all and will work if you are only interested in the relative order and not the actual value of your position field. That is to look up the FID value for any of uniqueId.

-
Awesome, it worked. I ended up using an ugly and probably inefficient combination of approaches, but it worked. I'll revisit the code when I'm better at Python and make it beautiful. The responses here provided key inspiration to get me over the hump. Awesome. – Nathaniel Apr 4 '12 at 6:31
Glad to help. When you get around to making your code beautiful, Google 'DRY' ('Don't Repeat Yorself'). It's a good coding principle along with others. ArcPy code generated from Model Builder is a great starting point but it is very 'dirty' and definitely NOT DRY! But, it get's you going. Clean code becomes a habit with practice ...well... to a certain extent anyway :) – MappaGnosis Apr 4 '12 at 16:13