Получить индексы 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 шт):
У вас в итоге должен получится словарь, судя по заданию. Непонятно, зачем здесь 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)]
Не совсем понятно, при чём тут 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)]
Если хотите оставаться именно в рамках 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 должна быть довольно быстрой.
В данном случае проще будет воспользоваться 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,)