Find row where values for column is maximal in a pandas DataFrame
Use the pandas
idxmax function. It's straightforward:
import pandasimport numpy as np df = pandas.DataFrame(np.random.randn(5,3),columns=['A','B','C']) df A B C0 1.232853 -1.979459 -0.5736261 0.140767 0.394940 1.0688902 0.742023 1.343977 -0.5797453 2.125299 -0.649328 -0.2116924 -0.187253 1.908618 -1.862934df['A'].argmax()3df['B'].argmax()4df['C'].argmax()1
Alternatively you could also use
numpy.argmax, such as
numpy.argmax(df['A'])-- it provides the same thing, and appears at least as fast as
idxmaxin cursory observations.
idxmax()returns indices labels, not integers.
- Example': if you have string values as your index labels, like rows 'a' through 'e', you might want to know that the max occurs in row 4 (not row 'd').
- if you want the integer position of that label within the
Indexyou have to get it manually (which can be tricky now that duplicate row labels are allowed).
idxmax()used to be called
argmax()prior to 0.11
argmaxwas deprecated prior to 1.0.0 and removed entirely in 1.0.0
- back as of Pandas 0.16,
argmaxused to exist and perform the same function (though appeared to run more slowly than
argmaxfunction returned the integer position within the index of the row location of the maximum element.
- pandas moved to using row labels instead of integer indices. Positional integer indices used to be very common, more common than labels, especially in applications where duplicate row labels are common.
For example, consider this toy
DataFrame with a duplicate row label:
In : dfrmOut: A B Ca 0.143693 0.653810 0.586007b 0.623582 0.312903 0.919076c 0.165438 0.889809 0.000967d 0.308245 0.787776 0.571195e 0.870068 0.935626 0.606911f 0.037602 0.855193 0.728495g 0.605366 0.338105 0.696460h 0.000000 0.090814 0.963927i 0.688343 0.188468 0.352213i 0.879000 0.105039 0.900260In : dfrm['A'].idxmax()Out: 'i'In : dfrm.iloc[dfrm['A'].idxmax()] # .ix instead of .iloc in older versions of pandasOut: A B Ci 0.688343 0.188468 0.352213i 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.
You might also try
In : df = pandas.DataFrame(np.random.randn(10,3),columns=['A','B','C'])In : dfOut: A B C0 2.001289 0.482561 1.5799851 -0.991646 -0.387835 1.3202362 0.143826 -1.096889 1.4865083 -0.193056 -0.499020 1.5365404 -2.083647 -3.074591 0.1757725 -0.186138 -1.949731 0.2874326 -0.480790 -1.771560 -0.9302347 0.227383 -0.278253 2.1020048 -0.002592 1.434192 -1.6249159 0.404911 -2.167599 -0.452900In : df.idxmax()Out: A 0B 8C 7
In : df.loc[df['A'].idxmax()]Out: A 2.001289B 0.482561C 1.579985
Both above answers would only return one index if there are multiple rows that take the maximum value. If you want all the rows, there does not seem to have a function.But it is not hard to do. Below is an example for Series; the same can be done for DataFrame:
In : from pandas import Series, DataFrameIn : s=Series([2,4,4,3],index=['a','b','c','d'])In : s.idxmax()Out: 'b'In : s[s==s.max()]Out: b 4c 4dtype: int64