ArcPy Geoprocessing – How to Find Max Value Among Fields and Print Field Name

arcgis-10.3arcpycursorgeoprocessing

I have a Census dataset that contains eight fields with percentages. I would like a python script that finds the highest value between the eight fields, but also tells me which field the highest value came from. I've gotten halfway there using Field Calculator in ArcMap 10.3, using the max(!field1!, !field2!, !field3!) script.

enter image description here

However, I also need it to be able to somehow add the field name because ultimately, the field name is what I want in a new indivisual field, and I will symbolize based on that field.

So far, my programmer colleague helped me come up with the following python script but I am getting an error message regarding my gp and not too python savvy to get it working.

import arcpy
fc = "C:/filename" #or shapefile address
gp = arcgisscripting.create()

# Create update cursor for feature class.
rows = gp.UpdateCursor(table)
row = rows.Next()

field_list = ["ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT"]

while row:

    highname_values = [row.GetValue(f) for f in field_list]
    zipped = zip(eth_values, field_list)
    zipped.sort(key=lambda t: t[0], reverse=True)
    row.highname = zipped[0][1] # replace ETH for the field that you want to update with the field name (ONE, TWO, ETC)
    row.HIGH = zipped[0][0]
    rows.UpdateRow(row)
    # Go to the next
    row = rows.Next()

Best Answer

Since your answer was tagged with , you'll find there is no need to use arcgisscripting. (I don't even know where to start with it to be honest.) You can also use the updated data access module cursors.

There's no need to use zip or any kind of sorting since you are accessing values on a per-row basis. As you mentioned, you can use field calculator to find the max, which would simplify this somewhat since you can just grab the maximum value inside the for loop instead of calculating it as I'm doing:

import arcpy

# input data and fields to find maximum
table = '<path to dataset>'
fields = ["F1","F2","F3","F4","F5"]
n = len(fields)


# Add fields to input table to store maximum and field name
maxfield = "HIGHEST"
maxname = "HIGHEST_name"
arcpy.AddField_management(table, maxfield, "SHORT")
arcpy.AddField_management(table, maxname, "TEXT")

fields2 = fields[:] # shallow copy
fields2.extend([maxfield, maxname])

with arcpy.da.UpdateCursor(table, fields2) as cursor:
    for row in cursor:

        # Look at the first n values        
        check = row[:n]
        maxval = max(check)

        # Get the index position of the maxval and use it slice into field list
        # which gives us the field name
        # only update the last two rows
        row[-2:] = maxval, fields[check.index(maxval)]

        cursor.updateRow(row)

enter image description here

As you can see, some of the maximum values are present in multiple fields. The .index() method only grabs the first occurrence, so you'll need to change a few things to get all the field names, if desired.