Ответ 1
У вас есть несколько хороших примеров того, как делать то, что вы хотите. Тем не менее, также полезно понять, что происходит и почему все работает так, как они делают. Есть несколько простых правил, которые помогут вам в будущем.
Существует большая разница между "фантазийным" индексированием (т.е. использованием списка/последовательности) и "нормальным" индексированием (с использованием среза). Основная причина связана с тем, можно ли "массировать" массив регулярно, и, следовательно, нужно ли делать копию. Поэтому произвольные последовательности должны обрабатываться по-разному, если мы хотим иметь возможность создавать "представления" без копирования.
В вашем случае:
import numpy as np
a = np.arange(100).reshape(10,10)
n1, n2 = np.arange(5), np.arange(5)
# Not what you want
b = a[n1, n2] # array([ 0, 11, 22, 33, 44])
# What you want, but only for simple sequences
# Note that no copy of *a* is made!! This is a view.
b = a[:5, :5]
# What you want, but probably confusing at first. (Also, makes a copy.)
# np.meshgrid and np.ix_ are basically equivalent to this.
b = a[n1[:,None], n2[None,:]]
Необычная индексация с 1D-последовательностями в основном эквивалентна их скреплению и индексированию с результатом.
print "Fancy Indexing:"
print a[n1, n2]
print "Manual indexing:"
for i, j in zip(n1, n2):
print a[i, j]
Однако, если последовательности, которые вы индексируете, соответствуют размерности массива, который вы индексируете (в данном случае 2D). Индексирование обрабатывается по-разному. Вместо того, чтобы "сжимать два вместе", numpy использует индексы наподобие маски.
Иными словами, a[[[1, 2, 3]], [[1],[2],[3]]]
трактуется совершенно иначе, чем a[[1, 2, 3], [1, 2, 3]]
, потому что последовательности/массивы, которые вы проходите, являются двумерными.
In [4]: a[[[1, 2, 3]], [[1],[2],[3]]]
Out[4]:
array([[11, 21, 31],
[12, 22, 32],
[13, 23, 33]])
In [5]: a[[1, 2, 3], [1, 2, 3]]
Out[5]: array([11, 22, 33])
Чтобы быть более точным,
a[[[1, 2, 3]], [[1],[2],[3]]]
обрабатывается точно так же:
i = [[1, 1, 1],
[2, 2, 2],
[3, 3, 3]])
j = [[1, 2, 3],
[1, 2, 3],
[1, 2, 3]]
a[i, j]
Другими словами, является ли входной вектор строки/столбца сокращением того, как индексы должны повторяться при индексировании.
np.meshgrid
и np.ix_
являются просто убедительными способами превратить ваши 1D-последовательности в их 2D-версии для индексирования:
In [6]: np.ix_([1, 2, 3], [1, 2, 3])
Out[6]:
(array([[1],
[2],
[3]]), array([[1, 2, 3]]))
Аналогично (аргумент sparse
сделал бы его идентичным с ix_
выше):
In [7]: np.meshgrid([1, 2, 3], [1, 2, 3], indexing='ij')
Out[7]:
[array([[1, 1, 1],
[2, 2, 2],
[3, 3, 3]]),
array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])]