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 ответов:
по данным документация
возвращает индексы, которые будут сортировать массив.
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