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

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

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

14 ответов

Решение

Вам просто нужно argmax() (сейчас называется 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

Эта функция была обновлена ​​до имени idxmax в Pandas API, хотя по состоянию на Pandas 0.16, argmax все еще существует и выполняет ту же функцию (хотя, кажется, работает медленнее, чем idxmax).

Вы также можете просто использовать numpy.argmax, такие как numpy.argmax(df['A']) - это обеспечивает то же самое, что и любой из двух pandas функции, и появляется по крайней мере так же быстро, как idxmax в кратких наблюдениях.

Ранее (как отмечено в комментариях) оказалось, что argmax будет существовать как отдельная функция, которая обеспечивает целочисленную позицию в индексе расположения строки максимального элемента. Например, если в качестве меток индекса используются строковые значения, такие как строки с "a" по "e", вы можете узнать, что максимальное значение происходит в строке 4 (а не в строке "d"). Тем не менее, в пандах 0.16 все перечисленные выше методы предоставляют метку только из Index для рассматриваемой строки, и если вы хотите, чтобы целое число позиции этой метки в пределах Index Вы должны получить его вручную (что может быть сложно, если разрешены дубликаты строк).

В общем думаю перейти на idxmax поведение для всех трех подходов (argmax, который все еще существует, idxmax, а также numpy.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.ix[dfrm['A'].idxmax()]
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 для вас, самостоятельно пишет ошибочную реализацию, редактирует код и молится, чтобы вы больше не сталкивались с проблемой,

Вы также можете попробовать 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

Оба приведенных выше ответа вернут только один индекс, если есть несколько строк, которые принимают максимальное значение. Если вы хотите, чтобы все строки, там, кажется, нет функции. Но это не сложно сделать. Ниже приведен пример для серии; то же самое можно сделать для 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
df.iloc[df['columnX'].argmax()]

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

Более компактное и удобочитаемое решение с использованием query() выглядит так:

      import pandas as pd

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

# find row with maximum A
df.query('A == A.max()')

Он также возвращает DataFrame вместо Series, что было бы удобно в некоторых случаях использования.

Очень просто: у нас есть df, как показано ниже, и мы хотим напечатать строку с максимальным значением в C:

A  B  C
x  1  4
y  2  10
z  5  9

В:

df.loc[df['C'] == df['C'].max()]   # condition check

Вне:

A B C
y 2 10

Если вам нужна вся строка, а не только id, вы можете использовать df.nlargest и передать, сколько "верхних" строк вы хотите, и вы также можете передать, для какого столбца / столбцов вы хотите это.

df.nlargest(2,['A'])

предоставит вам строки, соответствующие двум верхним значениям A.

использовать df.nsmallest для минимальных значений.

Прямое решение ".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()
mx.iloc[0].idxmax()

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

Учитывая этот фрейм данных

      [In]: df = pd.DataFrame(np.random.randn(4,3),columns=['A','B','C'])
[Out]:
          A         B         C
0 -0.253233  0.226313  1.223688
1  0.472606  1.017674  1.520032
2  1.454875  1.066637  0.381890
3 -0.054181  0.234305 -0.557915

Предполагая, что кто-то хочет знать строки, в которых столбец "C" является максимальным, следующее будет работать

      [In]: df[df['C']==df['C'].max()])
[Out]:
          A         B         C
1  0.472606  1.017674  1.520032

что сработало для меня:df[df['colX'] == df['colX'].max()

Затем вы получаете строку в своем df с максимальным значением colX.

Затем, если вам просто нужен индекс, вы можете добавить.indexв конце запроса.

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

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

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

Если есть связи в максимальных значениях, то возвращает индекс только первого максимального значения. Например, в следующем DataFrame:

         A  B  C
0  1  0  1
1  0  0  1
2  0  0  0
3  0  1  1
4  1  0  0

idxmaxвозвращается

      A    0
B    3
C    0
dtype: int64

Теперь, если мы хотим, чтобы все индексы соответствовали максимальным значениям, мы могли бы использовать max+ eqдля создания логического DataFrame, а затем используйте его на df.indexдля фильтрации индексов:

      out = df.eq(df.max()).apply(lambda x: df.index[x].tolist())

Выход:

      A       [0, 4]
B          [3]
C    [0, 1, 3]
dtype: object

Использовать:

      data.iloc[data['A'].idxmax()]

data['A'].idxmax()-находит положение максимального значения в строке data.iloc() — возвращает строку

Другие вопросы по тегам