Numpy argsort-что он делает?


почему numpy дает такой результат:

x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()

>[2 3 1 0]

когда я ожидаю, что он сделает это:

[3 2 0 1]

очевидно, что мое понимание функции отсутствует.

7 79

7 ответов:

по данным документация

возвращает индексы, которые будут сортировать массив.

  • 2 индекс 0.0.
  • 3 индекс 0.1.
  • 1 индекс 1.41.
  • 0 индекс 1.48.

[2, 3, 1, 0] указывает, что наименьший элемент находится в индексе 2, Следующий наименьший в индексе 3, затем индекс 1, затем индекс 0.

здесь несколько способов чтобы получить результат, который вы ищете:

import numpy as np
import scipy.stats as stats

def using_indexed_assignment(x):
    "https://stackoverflow.com/a/5284703/190597 (Sven Marnach)"
    result = np.empty(len(x), dtype=int)
    temp = x.argsort()
    result[temp] = np.arange(len(x))
    return result

def using_rankdata(x):
    return stats.rankdata(x)-1

def using_argsort_twice(x):
    "https://stackoverflow.com/a/6266510/190597 (k.rooijers)"
    return np.argsort(np.argsort(x))

def using_digitize(x):
    unique_vals, index = np.unique(x, return_inverse=True)
    return np.digitize(x, bins=unique_vals) - 1

например,

In [72]: x = np.array([1.48,1.41,0.0,0.1])

In [73]: using_indexed_assignment(x)
Out[73]: array([3, 2, 0, 1])

это проверяет, что все они дают один и тот же результат:

x = np.random.random(10**5)
expected = using_indexed_assignment(x)
for func in (using_argsort_twice, using_digitize, using_rankdata):
    assert np.allclose(expected, func(x))

Эти IPython %timeit бенчмарки предлагает для больших массивов using_indexed_assignment - это самый быстрый:

In [50]: x = np.random.random(10**5)
In [66]: %timeit using_indexed_assignment(x)
100 loops, best of 3: 9.32 ms per loop

In [70]: %timeit using_rankdata(x)
100 loops, best of 3: 10.6 ms per loop

In [56]: %timeit using_argsort_twice(x)
100 loops, best of 3: 16.2 ms per loop

In [59]: %timeit using_digitize(x)
10 loops, best of 3: 27 ms per loop

для небольших массивов, using_argsort_twice может быть быстрее:

In [78]: x = np.random.random(10**2)

In [81]: %timeit using_argsort_twice(x)
100000 loops, best of 3: 3.45 µs per loop

In [79]: %timeit using_indexed_assignment(x)
100000 loops, best of 3: 4.78 µs per loop

In [80]: %timeit using_rankdata(x)
100000 loops, best of 3: 19 µs per loop

In [82]: %timeit using_digitize(x)
10000 loops, best of 3: 26.2 µs per loop

обратите внимание также, что stats.rankdata дает вам больше контроля над тем, как обрабатывать элементы равной ценности.

Как документация говорит, argsort:

возвращает индексы, которые будут сортировать массив.

это означает, что первый элемент argsort-это индекс элемента, который должен быть отсортирован первым, второй элемент-это индекс элемента, который должен быть вторым и т. д.

то, что вы, кажется, хотите, это порядок рангов значений, который обеспечивается scipy.stats.rankdata. Обратите внимание, что вам нужно подумать о том, что должно произойти, если есть связи в рядах.

во-первых, он был заказан массива. Затем создайте массив с начальным индексом массива.

просто хочу напрямую сравнить исходное понимание OP с фактической реализацией с кодом.

numpy.argsort определение

x[x.argsort()] == numpy.sort(x) # this will be an array of True's

ОП первоначально думал, что он был определен таким образом, что

x == numpy.sort(x)[x.argsort()] # this will not be True

вход:
импорт включает в себя как НП
x = np.массив([1.48,1.41,0.0,0.1])
х.argsort().argsort ()

выход:
массив([3, 2, 0, 1])

np.argsort возвращает индекс отсортированного массива, заданный 'kind' (который определяет тип алгоритма сортировки). Однако, когда список используется с НП.argmax, он возвращает индекс самого большого элемента в списке. Пока, НП.сортировка, сортировка заданного массива, списка.