Почему numpy дает такой результат:
x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()
>[2 3 1 0]
когда я ожидал, что это сделает это:
[3 2 0 1]
Ясно, что мне не хватает понимания функции.
Почему numpy дает такой результат:
x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()
>[2 3 1 0]
когда я ожидал, что это сделает это:
[3 2 0 1]
Ясно, что мне не хватает понимания функции.
Ответы:
Согласно документации
Возвращает индексы для сортировки массива.
2
это индекс 0.0
.3
это индекс 0.1
.1
это индекс 1.41
.0
это индекс 1.48
.a = x.argsort()
, распечатайте x[a]
, получимarray([ 0. , 0.1 , 1.41, 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))
Эти %timeit
тесты IPython предлагают для больших массивов 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
возвращает второй вызов .
Как говорится в документацииargsort
:
Возвращает индексы для сортировки массива.
Это означает, что первый элемент argsort - это индекс элемента, который должен быть отсортирован первым, второй элемент - это индекс элемента, который должен быть вторым и т. Д.
Кажется, вам нужен порядок ранжирования значений, который предоставляется scipy.stats.rankdata
. Учтите, что нужно подумать о том, что должно произойти, если в строю будет ничья.
numpy.argsort (a, axis = -1, kind = 'quicksort', order = None)
Возвращает индексы для сортировки массива
Выполните косвенную сортировку по заданной оси, используя алгоритм, заданный ключевым словом kind. Он возвращает массив индексов той же формы, что и данные индекса по заданной оси в отсортированном порядке.
Рассмотрим один пример на Python, имеющий список значений как
listExample = [0 , 2, 2456, 2000, 5000, 0, 1]
Теперь воспользуемся функцией argsort:
import numpy as np
list(np.argsort(listExample))
Выход будет
[0, 5, 6, 1, 3, 2, 4]
Это список индексов значений в listExample, если вы сопоставите эти индексы с соответствующими значениями, тогда мы получим следующий результат:
[0, 0, 1, 2, 2000, 2456, 5000]
(Я считаю эту функцию очень полезной во многих местах, например, если вы хотите отсортировать список / массив, но не хотите использовать функцию list.sort () (т.е. без изменения порядка фактических значений в списке), вы можете использовать это функция).
Для получения дополнительных сведений перейдите по этой ссылке: https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.argsort.html
ввод:
импортировать numpy как np
x = np.array ([1.48,1.41,0.0,0.1])
x.argsort (). argsort ()
вывод:
массив ([3, 2, 0, 1])
Сначала был заказан массив. Затем сгенерируйте массив с начальным индексом массива.
np.argsort возвращает индекс отсортированного массива, заданный параметром "kind" (который указывает тип алгоритма сортировки). Однако, когда список используется с np.argmax, он возвращает индекс самого большого элемента в списке. В то время как np.sort сортирует данный массив list.
Просто хочу прямо противопоставить исходное понимание OP и фактическую реализацию с кодом.
numpy.argsort
определяется так, что для одномерных массивов:
x[x.argsort()] == numpy.sort(x) # this will be an array of True's
OP изначально думал, что он был определен таким образом, что для одномерных массивов:
x == numpy.sort(x)[x.argsort()] # this will not be True
Примечание: этот код не работает в общем случае (работает только для 1D), этот ответ предназначен исключительно для целей иллюстрации.
x[x.argsort()]
не обязательно то же самое, что np.sort(x)
. На самом деле, это даже не обязательно одна и та же форма. Попробуйте это с 2D-массивом. Это происходит только при работе с одномерными массивами.
[3 2 0 1]
был правильный ответ?