Getting the field name that contains a max value in python

2928
7
06-27-2018 11:17 AM
MaraKaminowitz
Occasional Contributor

I am trying to get the name of a field that contains the maximum value across several rows.  Getting the maximum number is easy, I would just use max(a, b, c...).  But I would like the field name of that is associated with each high value.  Example:

F1F2F3
2348
1941
3722

So max in python would give me

34

19

22

But what I want is

F2

F1

F3

Any suggestions? 

7 Replies
JonathanQuinn
Esri Notable Contributor

A search cursor reads each column, so you can iterate through the columns to find the largest value:

from arcpy import da

field_names=["F1","F2","F3"]

with arcpy.da.SearchCursor(r"Data",field_names) as cursor:
    #Iterate through records
    for row in cursor:
        #Iterate through columns
        for val in row:
            #If it's the first record, set the maxVal variable to the record
            if row.index(val) == 0:
                maxVal = val
            else:
                if val > maxVal:
                    maxVal = val
           #Or, set it to 0 by default if you know all values are positive
           ##maxVal = 0
           ##if val > maxVal:
           ##    maxVal = val
        #Then, use indexing to get the field names
        print(field_names[row.index(maxVal)])‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
JoshuaBixby
MVP Esteemed Contributor

This approach can be simplified a bit:

import arcpy

tbl = # path to table or feature class
flds = ["F1", "F2", "F3"]

with arcpy.da.SearchCursor(tbl, flds) as cur:
    for row in cur:
        print(cur.fields[row.index(max(row))])
MaraKaminowitz
Occasional Contributor

Thanks.  I have a large number of fields.  Adding them all into the script isn't hard but for education's sake, is there a way to read them into a single variable?  I tried incorporating another for loop to iterate through the field names and feed that into the search cursor, but I just created a mess.  I started with

field_names = arcpy.ListFields(featureclass, 'Sum_*')

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

You are on the right track.  ListFields—Help | ArcGIS Desktop  doesn't return a list of names, it returns a list of field objects, which you need to extract the names from the objects:

field_names = [fld.name for fld in arcpy.ListFields(featureclass, 'Sum_*')]
DanPatterson_Retired
MVP Emeritus

Mara

ListFields returns field objects not their names...

So you could do this

field_names = [f.name for f in arcpy.ListFields(featureclass, 'Sum_')]
DanPatterson_Retired
MVP Emeritus

Forgot the * in the wildcard... as in Joshua's...

More on....

Listing Data

A wildcard defines a name filter, and all the contents in the newly created list must pass that filter. For example, you may want to list all the feature classes in a workspace that start with the letter G 

fcs = arcpy.ListFeatureClasses("G*")

0 Kudos
DanPatterson_Retired
MVP Emeritus

For the field calculator

def find_max(flds, names=None):
    """puthon parser
    flds - a list of fields [!a!, !b!, !c!]
    names - a list of field names [a, b, c] 
    in_ = [a, b, c]
    useage : find_max([!a!, !b!, !c!], [a, b, c])
    """
    if (flds is None) or (names is None):
        return None
    else:
        return names[flds.index(max(flds))]
    



find_max([!a!, !b!, !c!], [a, b, c])

# ---- assume [9, 2, 13] for [!a!, !b!, !c!] for example

'c'