Получить индексы Numpy массива

Всем привет.

У меня есть такой Numpy массив:

array([16, 17, 1, 3, 8, 10, 2, 19, 14, 18, 15, 6, 11, 13, 5, 4, 9, 0, 7, 12])

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

[19: 7, 18: 9, 17: 1, 16: 0, 15: 10 ...]

То есть, в итоговом списке я должен отсортировать по снижение значений из первого списка, но при этом нужно добавить какой был индекс у базового списка для каждого элемента. И сделать это надо самым быстрым способом. Я имею представление как это сделать, но оно как-то сложно выходит. Может быть у numpy есть быстрее способ?


Ответы (4 шт):

Автор решения: strawdog

У вас в итоге должен получится словарь, судя по заданию. Непонятно, зачем здесь numpy, но если вам нужно именно с ним, то можно так:

a = np.array([16, 17, 1, 3, 8, 10, 2, 19, 14, 18, 15, 6, 11, 13, 5, 4, 9, 0, 7, 12])
res = { x[1]:x[0][0] for x in np.ndenumerate(a)}
res = dict(sorted(res.items(), key=lambda item: item[0], reverse=True))

res:

{19: 7,
 18: 9,
 17: 1,
 16: 0,
 15: 10,
 14: 8,
 13: 13,
 12: 19,
 11: 12,
 10: 5,
 9: 16,
 8: 4,
 7: 18,
 6: 11,
 5: 14,
 4: 15,
 3: 3,
 2: 6,
 1: 2,
 0: 17}

UPDATE (если значения могут повторятся)

в этом случае нужно использовать кортежи или списки:

import numpy as np

a = np.array([16, 16, 16, 3, 8, 10])

res = [(x[1],x[0][0]) for x in np.ndenumerate(a)]
res = sorted(res, key=lambda item: item[0], reverse=True)

res:

[(16, 0), (16, 1), (16, 2), (10, 5), (8, 4), (3, 3)]
→ Ссылка
Автор решения: CrazyElf

Не совсем понятно, при чём тут numpy, и какая структура нужна на выходе. Вот список кортежей для разнообразия, потому что сортировать словарь особого смысла не вижу вообще:

arr = [16, 17, 1, 3, 8, 10, 2, 19, 14, 18, 15, 6, 11, 13, 5, 4, 9, 0, 7, 12]
print(sorted(((x, i) for i, x in enumerate(arr)), reverse=True))

Вывод:

[(19, 7), (18, 9), (17, 1), (16, 0), (15, 10), (14, 8), (13, 13), (12, 19), (11, 12), (10, 5), (9, 16), (8, 4), (7, 18), (6, 11), (5, 14), (4, 15), (3, 3), (2, 6), (1, 2), (0, 17)]
→ Ссылка
Автор решения: CrazyElf

Если хотите оставаться именно в рамках numpy и пользоваться его скоростью, то можно сделать так:

import numpy as np

arr = np.array([16, 17, 1, 3, 8, 10, 2, 19, 14, 18, 15, 6, 11, 13, 5, 4, 9, 0, 7, 12])
sorted_idx = arr.argsort()[::-1]
sorted_arr = arr[sorted_idx]
print(np.stack([sorted_arr, sorted_idx]))

Вывод:

[[19 18 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0]
 [ 7  9  1  0 10  8 13 19 12  5 16  4 18 11 14 15  3  6  2 17]]

В numpy есть сортировка индексов массива. Тут я получаю сначала такую сортировку, переворачиваю её, чтобы в начале был максимум, потом легко получить значения из массива по индексам. Ну и, если нужно - объединить индексы и значения в один массив. Сортировка индексов в numpy должна быть довольно быстрой.

→ Ссылка
Автор решения: MaxU

В данном случае проще будет воспользоваться Pandas:

In [17]: a = np.array([16, 17, 1, 3, 8, 10, 2, 19, 14, 18, 15, 6, 11, 13, 5, 4, 9, 0, 7, 12])

In [18]: s = pd.Series(np.arange(len(a)), index=a)

In [19]: res = s.sort_index(ascending=False)

In [20]: res
Out[20]:
19     7
18     9
17     1
16     0
15    10
14     8
13    13
12    19
11    12
10     5
9     16
8      4
7     18
6     11
5     14
4     15
3      3
2      6
1      2
0     17
dtype: int64

замер скорости для 1.000.000 элементов:

In [21]: a = np.random.randint(1000, size=10**6)

In [22]: s = pd.Series(np.arange(len(a)), index=a)

In [23]: %timeit s.sort_index(ascending=False)
107 ms ± 2.82 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [24]: s.shape
Out[24]: (1000000,)
→ Ссылка