Расширенная целочисленная нарезка, когда нарезка объекта является кортежем 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
поместив эти индексные массивы в их координатные позиции в []
выражение.