Найти строку, где значения столбца максимальны в панде DataFrame

209

Как найти строку, для которой значение определенного столбца является максимальным ?

df.max() даст мне максимальное значение для каждого столбца, я не знаю, как получить соответствующую строку.

lazy1
источник
Можно ли получить верхние 2 значения? а не только макс?
AsheKetchum
5
Вы можете использовать sort_valuesи получить индекс:df.sort_values('col', ascending=False)[:2].index
lazy1
2
lazy1: избегайте ненужной сортировки всей серии, потому что это в среднем O (N logN), тогда как нахождение max / idxmax составляет только O (N).
SMCI

Ответы:

240

Используйте idxmaxфункцию панд . Это просто:

>>> 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'].argmax()
3
>>> df['B'].argmax()
4
>>> df['C'].argmax()
1
  • В качестве альтернативы вы также можете использовать numpy.argmax, например, numpy.argmax(df['A'])- он обеспечивает то же самое и появляется по крайней мере так же быстро, как и idxmaxпри поверхностных наблюдениях.

  • idxmax() возвращает метки индексов, а не целые числа.

    • Пример ': если в качестве меток индекса используются строковые значения, например строки от' a 'до' e ', вы можете знать, что максимальное значение происходит в строке 4 (а не в строке' d ').
    • если вам нужна целочисленная позиция этой метки внутри, Indexвы должны получить ее вручную (что может быть непросто, если разрешить дублирование меток строк).

ИСТОРИЧЕСКИЕ ЗАМЕЧАНИЯ:

  • idxmax()раньше вызывался argmax()до 0.11
  • argmax устарела до 1.0.0 и полностью удалена в 1.0.0
  • Начиная с Pandas 0.16, argmaxраньше существовал и выполнял ту же функцию (хотя, казалось, работал медленнее, чем idxmax).
    • argmaxФункция вернула целочисленную позицию в индексе расположения строки максимального элемента.
    • Панды перешли на использование меток строк вместо целочисленных индексов.Позиционные целочисленные индексы раньше были очень распространенными, более распространенными, чем метки, особенно в приложениях, где встречаются повторяющиеся метки строк.

Например, рассмотрим эту игрушку DataFrame с двойной строкой ярлыка:

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

Так вот наивное использование idxmaxне является достаточным, в то время как старая форма argmaxбудет правильно предоставить позиционное расположение максимального ряда (в данном случае, положение 9).

Это как раз один из тех неприятных видов поведения, склонного к ошибкам в динамически типизированных языках, который делает такие вещи такими неудачными и стоит побить мертвую лошадь. Если вы пишете системный код, и ваша система внезапно используется для некоторых наборов данных, которые не были очищены должным образом перед объединением, очень легко получить дубликаты меток строк, особенно меток строк, таких как идентификатор CUSIP или SEDOL для финансовых активов. Вы не можете легко использовать систему типов, чтобы помочь вам, и вы не сможете обеспечить уникальность индекса, не столкнувшись с неожиданно отсутствующими данными.

Таким образом, у вас остается надежда, что ваши юнит-тесты покрыли все (они этого не сделали, или, скорее всего, никто не написал никаких тестов) - иначе (скорее всего) вы просто остаетесь ждать, чтобы увидеть, не случится ли это ошибка во время выполнения, в этом случае вы , вероятно , придется идти падение много часов на сумму работы из базы данных вы выводя результаты, биться головой о стену в IPython пытается вручную воспроизвести проблему, наконец , выяснить , что это потому , что idxmaxможет только сообщите метку строки max, а затем разочаровываетесь, что ни одна стандартная функция автоматически не получает позиции строки max для вас, вы сами пишете ошибочную реализацию, редактируете код и молитесь, чтобы вы больше не сталкивались с проблемой.

Ely
источник
13
Основываясь на последнем комментарии, он выглядит argminи argmaxостанется частью, DataFrameа разница в том, хотите ли вы индекс или метку. idxmaxдаст вам метку места, где происходит макс. argmaxдаст вам целое число индекса.
Ely
4
Предоставленная информация, чтобы объяснить разницу между argmaxи idxmax, и как избежать ошибок с дублированным индексом, была отличной! Я не заметил этого, пока не прочитал ваш комментарий в другом ответе. Спасибо!
Тупан
Что касается использования, которое вы хотели бы реализовать, Pandas 0.24.1 указывает на следующее: «поведение argmaxбудет исправлено, чтобы вернуть позиционный максимум в будущем. А пока используйте series.values.argmaxили, np.argmax(np.array(values))чтобы получить позицию максимального ряда. '
Сэм
1
аналогично, .ixметод второго примера был переименован в.iloc
Ma0
если ваш столбец содержит только значения nan, это приведет к TypeError
Max Segal
77

Вы также можете попробовать idxmax:

In [5]: df = pandas.DataFrame(np.random.randn(10,3),columns=['A','B','C'])

In [6]: df
Out[6]: 
          A         B         C
0  2.001289  0.482561  1.579985
1 -0.991646 -0.387835  1.320236
2  0.143826 -1.096889  1.486508
3 -0.193056 -0.499020  1.536540
4 -2.083647 -3.074591  0.175772
5 -0.186138 -1.949731  0.287432
6 -0.480790 -1.771560 -0.930234
7  0.227383 -0.278253  2.102004
8 -0.002592  1.434192 -1.624915
9  0.404911 -2.167599 -0.452900

In [7]: df.idxmax()
Out[7]: 
A    0
B    8
C    7

например

In [8]: df.loc[df['A'].idxmax()]
Out[8]: 
A    2.001289
B    0.482561
C    1.579985
Уэс МакКинни
источник
Спасибо Уэс. Документация для idxmax () здесь: pandas.pydata.org/pandas-docs/dev/generated/…
будет
df.ix[df['A'].idxmax()].valuesзахватить массив, который я хотел. до сих пор работает.
Йоджимбо
2
Обратите внимание, что вы должны быть осторожны, пытаясь использовать выходные данные idxmaxв качестве фидера ixили locв качестве средства для среза данных и / или для получения позиционного положения максимальной строки. Потому что вы можете иметь дубликаты в Index- см. Обновление к моему ответу для примера.
августа
25

Оба приведенных выше ответа вернут только один индекс, если есть несколько строк, которые принимают максимальное значение. Если вы хотите, чтобы все строки, там, кажется, нет функции. Но это не сложно сделать. Ниже приведен пример для серии; то же самое можно сделать для DataFrame:

In [1]: from pandas import Series, DataFrame

In [2]: s=Series([2,4,4,3],index=['a','b','c','d'])

In [3]: s.idxmax()
Out[3]: 'b'

In [4]: s[s==s.max()]
Out[4]: 
b    4
c    4
dtype: int64
mxia
источник
10
Спасибо! версия для DataFrame:df[df['A'] == df['A'].max()]
Денис Голомазов
Это действительно правильный ответ (версия DataFrame).
gented
12
df.iloc[df['columnX'].argmax()]

argmax()предоставил бы индекс, соответствующий максимальному значению для columnX. ilocможет использоваться для получения строки DataFrame df для этого индекса.

Нафиз Курайши
источник
4

Прямое решение ".argmax ()" не работает для меня.

Предыдущий пример предоставлен @ely

>>> 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'].argmax()
3
>>> df['B'].argmax()
4
>>> df['C'].argmax()
1

возвращает следующее сообщение:

FutureWarning: 'argmax' is deprecated, use 'idxmax' instead. The behavior of 'argmax' 
will be corrected to return the positional maximum in the future.
Use 'series.values.argmax' to get the position of the maximum now.

Так что мое решение:

df['A'].values.argmax()
AntoineP
источник
2
mx.iloc[0].idxmax()

Эта строка кода покажет вам, как найти максимальное значение из строки в фрейме данных, вот mxфрейм данных и iloc[0]указывает 0-й индекс.

Манджула Деви
источник
1

Объект idmaxDataFrame возвращает индекс метки строки с максимальным значением, и поведение argmaxзависит от версии pandas(сейчас он возвращает предупреждение). Если вы хотите использовать позиционный индекс , вы можете сделать следующее:

max_row = df['A'].values.argmax()

или

import numpy as np
max_row = np.argmax(df['A'].values)

Обратите внимание, что если вы используете, np.argmax(df['A'])ведет себя так же, как df['A'].argmax().

Джонатан
источник