Computing new attribute based on changes in another attribute using ArcGIS Desktop with Python?

For this you can use UpdateCursor, which opens the feature class or table and steps through each record (row) incrementally.

The script below works on this test data

+-----------------------+
| Time| Home_Away|Trip  |
+-----|----------|------+
|  1  |  0       | <nul>|
|  2  |  1       | <nul>|
|  4  |  1       | <nul>|
|  5  |  0       | <nul>|
|  6  |  0       | <nul>|
|  7  |  1       | <nul>|
|  9  |  1       | <nul>|
| 12  |  1       | <nul>|
| 13  |  0       | <nul>|
+-----------------------+

.

import arcpy
fc = r'D:\s\py\pyscratch.gdb\gps_points'

# open the feature class and create the cursor
rows = arcpy.UpdateCursor(fc)

trip = 0
for row in rows:
    if row.HOME_AWAY == 0:
        trip += 1           # start of new trip, increment counter
        row.TRIP = trip     # calc the TRIP field to be current trip#
        rows.updateRow(row) # save
        print "Trip %s started at %s" % (trip, row.TIME)

    # keep cycling through records until HOME_AWAY is not 1
    while row.HOME_AWAY == 1:
        row.TRIP = trip
        rows.updateRow(row)
        rows.next() # move to next record

    # this is for the trailing end of a trip, the second 0
    # print "     %s ended at %s" % (trip, row.TIME)
    row.TRIP = trip
    rows.updateRow(row)

# remove programming objects and data locks
# the data itself is left alone
del row, rows

The trailing end of trip block is actually run for the beginning of a trip also, but since the trip counter is correct the double calc on the begin-trip-row doesn't matter . Uncomment the print statement in that block to see what I mean.

Python automatically adds an implicit rows.next() at the end for the for row in rows block.

This assumes data integrity. It will mess up if there are ever an odd number of zero Home/Away records in a row (000 or 00000). A trip that only consists of start and stop should be okay, e.g. a 3 trip sequence of 01..10 00 01..10 , where the spaces denote the gaps between trips. In other words, validate the results!


The ArcGIS 10 help under "calculate field examples" shows you how to "Calculate the accumulative value of a numeric field." This will do the trick, provided the data are physically in the intended temporal order.

To apply it directly, invert your [Home/Away] indicator (subtract it from 1) so that "0" means "away" and "1" means "home". I call this [Away/Home] in the example below.

Compute its cumulative value--[Cumulative] in the example.

Add one and divide by two--[Trip] in the example (almost).

Finally, set [Trip] to zero for all the "home" records. Now the results agree with the example:

Time Lat Lon Home/Away Trip Away/Home Cumulative 
   1   *   *         0    0         1          1
   2   *   *         1    1         0          1
   3   *   *         1    1         0          1
.... 
  12   *   *         1    1         0          1
  13   *   *         0    0         1          2
  14   *   *         0    0         1          3
  15   *   *         1    2         0          3
  16   *   *         1    2         0          3
.... 
  34   *   *         1    2         0          3
  35   *   *         0    0         1          4
  36   *   *         0    0         1          5
  37   *   *         1    3         0          5
....

For the record, here's the code taken from the ArcGIS 10 help. I modified it slightly so it would do every step at once: now you only need to run it. It should be clear where [Home/Away] gets inverted and where the "add 1, divide by 2" step occurs.

Expression:

acc(!Home/Away!)

Expression Type:

PYTHON_9.3

Code Block:

t=0
def acc(i):
  global t
  if t:
    t += (1-i)
  else:
    t = 1
  if i:
    return (t+1)/2
  else:
    return 0