Расширенная целочисленная нарезка, когда нарезка объекта является кортежем ndarray

Я понимаю как

x=np.array([[1, 2], [3, 4], [5, 6]] 
y = x[[0,1,2], [0,1,0]] 

Выход дает y= [1 4 5] Это просто берет первый список в виде списка строк и секунд и столбцов.

Но как работает ниже?

x = np.array([[ 0,  1,  2],[ 3,  4,  5],[ 6,  7,  8],[ 9, 10, 11]]) 

rows = np.array([[0,0],[3,3]])
cols = np.array([[0,2],[0,2]]) 
y = x[rows,cols] 

Это дает вывод:

[[ 0  2]                                                                      
 [ 9 11]] 

Можете ли вы объяснить логику при использовании ndarrays в качестве нарезки объекта? Почему у него есть двухмерный массив для строк и столбцов. Чем отличаются правила, когда объект среза является ndarray, а не списком python?

3 ответа

Решение

У нас есть следующий массив x

x = np.array([[1, 2], [3, 4], [5, 6]] 

И показатели [0, 1, 2] а также [0, 1, 0] который при индексации в x лайк

x[[0,1,2], [0,1,0]] 

дает

[1,  4,  5]

Индексы, которые мы использовали, в основном переводятся в:

[0, 1, 2] & [0, 1, 0] --> [0,0], [1,1], [2,0]

Поскольку мы использовали 1D список в качестве индексов, мы получаем 1D массив в качестве результата.


С этим знанием, давайте посмотрим на следующий случай. Теперь у нас есть массив x как:

x = np.array([[ 0,  1,  2],[ 3,  4,  5],[ 6,  7,  8],[ 9, 10, 11]]) 

Теперь индексы являются двумерными массивами.

rows = np.array([[0,0],[3,3]])
cols = np.array([[0,2],[0,2]]) 

Это когда индексируется в массив x лайк:

x[rows,cols] 

просто переводится как:

[[0,0],[3,3]]
  | |   | |      ====> [[0,0]], [[0,2]], [[3,0]], [[3,2]]
[[0,2],[0,2]]

Теперь легко наблюдать, как эти 4 list of list при индексации в массиве x даст следующий результат (т.е. здесь он просто возвращает угловые элементы из нашего массива x):

[[ 0,  2]                                                                      
 [ 9, 11]]

Обратите внимание, что в этом случае мы получаем результат в виде 2D-массива (в отличие от 1D-массива в первом случае), поскольку наши индексы rows & columns сами по себе были двумерные массивы (т.е. эквивалентно list of list) тогда как в первом случае наши индексы были одномерными массивами (или эквивалентно простыми list без вложенности).

Таким образом, если вам нужны 2D-массивы в качестве результата, вы должны предоставить 2D-массивы в качестве индексов.

Для простоты мы останемся 2D и предположим, rows.shape знак равно cols.shape, (Вы можете нарушить это правило с помощью трансляции, но пока мы не будем). Мы назовем эту форму (I, J)

затем y = x[rows, cols] такой же как:

y = np.empty((I, J))
for i in range(I):
    for j in range(J):
        y[i, j] = x[rows[i, j], cols[i, j]]

Самый простой способ обернуть голову вокруг этого - это следующее наблюдение: Форма вывода определяется формой индексного массива, или, точнее, формой, полученной в результате широковещательной передачи всех индексных массивов вместе.

Посмотрите на это так: у вас есть массив A заданной формы и другого массива V какой-то другой формы, и вы хотите заполнить A со значениями от V, Что нужно указать? Ну, для каждой позиции в A вам нужно указать координаты некоторого элемента в V, Поэтому если V ND вам нужно N индексных массивов той же формы, что и A или, по крайней мере, транслируется на это. Тогда вы индексируете V поместив эти индексные массивы в их координатные позиции в [] выражение.

Другие вопросы по тегам