Нарезка массивов со списками - PullRequest
8 голосов
/ 14 января 2020

Итак, я создаю массив numpy:

a = np.arange(25).reshape(5,5)

массив ([[0, 1, 2, 3, 4], [5, 6 , 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19], [20, 21, 22, 23, 24]])

Обычный срез a[1:3,1:3] возвращает массив

([[6, 7], [11, 12]])

, как и при использовании списка во втором массиве a[1:3,[1,2]]

([[6, 7], [11, 12]])

Однако a[[1,2],[1,2]] возвращает

массив ([6, 12])

Очевидно, я чего-то здесь не понимаю. Тем не менее, нарезка со списком может быть очень полезной.

Приветствия,

Кенг

Ответы [ 4 ]

2 голосов
/ 14 января 2020

Вы наблюдали эффект так называемой Advanced Indexing . Давайте рассмотрим пример по ссылке:

import numpy as np
x = np.array([[1, 2], [3, 4], [5, 6]])
print(x)
[[1 2]
 [3 4]
 [5 6]]
print(x[[0, 1, 2], [0, 1, 0]])  # [1 4 5]

Вы можете подумать об этом как о предоставлении списков (декартовых) координат сетки, как

print(x[0,1])  # 1
print(x[1,1])  # 4
print(x[2,0])  # 5
0 голосов
/ 14 января 2020

a[[1,2],[1,2]] читает это как, я хочу [1,1] и [2,2]. Есть несколько способов обойти это, и я, вероятно, даже не имею лучших способов, но вы можете попробовать

a[[1,1,2,2],[1,2,1,2]]

Это даст вам упрощенную версию выше

a[[1,2]][:,[1,2]]

Это даст вам правильный срез, он работает, принимая строки [1,2], а затем столбцы [1,2].

0 голосов
/ 14 января 2020

Он запускает расширенное индексирование , поэтому первый фрагмент - это индекс строки, второй - индекс столбца. Для каждой строки выбирается соответствующий столбец.

a[[1,2], [1,2]] -> [a[1, 1], a[2, 2]] -> [6, 12]
0 голосов
/ 14 января 2020

В последнем случае два отдельных списка обрабатываются как отдельные операции индексации (это очень неудобная формулировка, поэтому, пожалуйста, потерпите меня).

Numpy видит два списка из двух целых чисел и решает, что вы поэтому просят два значения. Индекс строки каждого значения происходит из первого списка, а индекс столбца каждого значения - из второго списка. Следовательно, вы получаете a[1,1] и a[2,2]. Обозначение : не только расширяет список, который вы точно вывели, но также сообщает numpy, что вы хотите все строки / столбцы в этом диапазоне.

Если вы указываете вручную индексы списка, они должны быть одинакового размера, потому что размер каждого / любого списка - это количество элементов, которые вы получите. Например, если вы хотели, чтобы элементы в столбцах 1 и 2 строк 1,2,3:

>>> a[1:4,[1,2]]
array([[ 6,  7],
       [11, 12],
       [16, 17]])

Но

>>> a[[1,2,3],[1,2]]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (2,)

Первый говорит numpy, что вы хотите диапазон строк и спецификаций c столбцов, в то время как последний говорит: «доставь мне элементы в (1,1), (2,2) и (3, hey! what the?! where's the other index?)»

...