Ключом к правильному пониманию является понимание роли индексирования списков и кортежей. Часто они обрабатываются одинаково, но в numpy
индексирование, кортежи, списки и массивы передают разную информацию.
In [1]: a = np.arange(12).reshape(3,4)
In [2]: t = np.array([(0,0),(1,1),(2,2)])
In [4]: a
Out[4]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In [5]: t
Out[5]:
array([[0, 0],
[1, 1],
[2, 2]])
Вы пробовали:
In [6]: a[t]
Out[6]:
array([[[ 0, 1, 2, 3],
[ 0, 1, 2, 3]],
[[ 4, 5, 6, 7],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[ 8, 9, 10, 11]]])
Так что же с этим не так? ? Он запустился, но выбрал (3,2) массив строк a
. То есть он применил t
только к первому измерению, фактически a[t, :]
. Вы хотите индексировать по всем измерениям, что-то вроде a[t1, t2]
. Это то же самое, что и a[(t1,t2)]
- кортеж индексов.
In [10]: a[tuple(t[0])] # a[(0,0)]
Out[10]: 0
In [11]: a[tuple(t[1])] # a[(1,1)]
Out[11]: 5
In [12]: a[tuple(t[2])]
Out[12]: 10
или выполнение всего сразу:
In [13]: a[(t[:,0], t[:,1])]
Out[13]: array([ 0, 5, 10])
Другой способ написать это - n
списки (илимассивы), по одному для каждого измерения:
In [14]: a[[0,1,2],[0,1,2]]
Out[14]: array([ 0, 5, 10])
In [18]: tuple(t.T)
Out[18]: (array([0, 1, 2]), array([0, 1, 2]))
In [19]: a[tuple(t.T)]
Out[19]: array([ 0, 5, 10])
В общем случае в a[idx1, idx2]
массив idx1
передается против idx2
для создания полного массива выбора. Здесь 2 массива 1d и совпадают, выбор - ваш набор пар t
. Но тот же принцип применим к выбору набора строк и столбцов: a[ [[0],[2]], [0,2,3] ]
.
Используя идеи из [10] и далее, ваш get
может быть ускорен:
In [20]: def get(a, t):
...: res = []
...: for ind in t:
...: res.append(a[tuple(ind)]) # index all dimensions at once
...: return res
...:
In [21]: get(a,t)
Out[21]: [0, 5, 10]
Если бы t
действительно был списком кортежей (в отличие от массива, построенного из них), ваш get мог бы быть:
In [23]: tl = [(0,0),(1,1),(2,2)]
In [24]: [a[ind] for ind in tl]
Out[24]: [0, 5, 10]