pythonpandasdataframerowargmax

Find row where values for column is maximal in a pandas DataFrame


How can I find the row for which the value of a specific column is maximal?

df.max() will give me the maximal value for each column, I don't know how to get the corresponding row.


Solution

  • Use the pandas idxmax function. It's straightforward:

    >>> import pandas
    >>> import numpy as np
    >>> df = pandas.DataFrame(np.random.randn(5,3),columns=['A','B','C'])
    >>> df
              A         B         C
    0  1.232853 -1.979459 -0.573626
    1  0.140767  0.394940  1.068890
    2  0.742023  1.343977 -0.579745
    3  2.125299 -0.649328 -0.211692
    4 -0.187253  1.908618 -1.862934
    >>> df['A'].idxmax()
    3
    >>> df['B'].idxmax()
    4
    >>> df['C'].idxmax()
    1
    

    HISTORICAL NOTES:

    For example, consider this toy DataFrame with a duplicate row label:

    In [19]: dfrm
    Out[19]: 
              A         B         C
    a  0.143693  0.653810  0.586007
    b  0.623582  0.312903  0.919076
    c  0.165438  0.889809  0.000967
    d  0.308245  0.787776  0.571195
    e  0.870068  0.935626  0.606911
    f  0.037602  0.855193  0.728495
    g  0.605366  0.338105  0.696460
    h  0.000000  0.090814  0.963927
    i  0.688343  0.188468  0.352213
    i  0.879000  0.105039  0.900260
    
    In [20]: dfrm['A'].idxmax()
    Out[20]: 'i'
    
    In [21]: dfrm.iloc[dfrm['A'].idxmax()]  # .ix instead of .iloc in older versions of pandas
    Out[21]: 
              A         B         C
    i  0.688343  0.188468  0.352213
    i  0.879000  0.105039  0.900260
    

    So here a naive use of idxmax is not sufficient, whereas the old form of argmax would correctly provide the positional location of the max row (in this case, position 9).

    This is exactly one of those nasty kinds of bug-prone behaviors in dynamically typed languages that makes this sort of thing so unfortunate, and worth beating a dead horse over. If you are writing systems code and your system suddenly gets used on some data sets that are not cleaned properly before being joined, it's very easy to end up with duplicate row labels, especially string labels like a CUSIP or SEDOL identifier for financial assets. You can't easily use the type system to help you out, and you may not be able to enforce uniqueness on the index without running into unexpectedly missing data.

    So you're left with hoping that your unit tests covered everything (they didn't, or more likely no one wrote any tests) -- otherwise (most likely) you're just left waiting to see if you happen to smack into this error at runtime, in which case you probably have to go drop many hours worth of work from the database you were outputting results to, bang your head against the wall in IPython trying to manually reproduce the problem, finally figuring out that it's because idxmax can only report the label of the max row, and then being disappointed that no standard function automatically gets the positions of the max row for you, writing a buggy implementation yourself, editing the code, and praying you don't run into the problem again.