Индексирование каждого второго блока 2x2 в 2D-массиве

Скажем, у меня есть массив, который выглядит как

array([[ 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, 25, 26, 27, 28, 29, 30, 31],
       [32, 33, 34, 35, 36, 37, 38, 39],
       [40, 41, 42, 43, 44, 45, 46, 47],
       [48, 49, 50, 51, 52, 53, 54, 55],
       [56, 57, 58, 59, 60, 61, 62, 63]])

И я хотел извлечь следующий массив:

array([[ 0,  1, 4,  5],
       [ 8,  9, 12, 13],
       [32, 33, 36, 37],
       [40, 41, 44, 45]])

По сути, это верхний левый блок 2x2 в каждом макроблоке 4x4. Я видел этот пример в 1D, но не мог понять 2D-вариант. Другой способ, о котором я могу думать, это:

h, w = full.shape
X, Y = np.meshgrid(np.arange(w), np.arange(h))
tl = full[(X%4<2) & (Y%4<2)].reshape((h//2,-1))

Но мне интересно, есть ли более чистый способ сделать это.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вот один из способов сделать это:

In [73]: a
Out[73]: 
array([[ 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, 25, 26, 27, 28, 29, 30, 31],
       [32, 33, 34, 35, 36, 37, 38, 39],
       [40, 41, 42, 43, 44, 45, 46, 47],
       [48, 49, 50, 51, 52, 53, 54, 55],
       [56, 57, 58, 59, 60, 61, 62, 63]])

In [74]: nr, nc = [s // 2 for s in a.shape]  # Shape of the new array

In [75]: b = a.reshape((nr, 2, nc, 2))[::2, :, ::2, :].reshape(nr, nc)

In [76]: b
Out[76]: 
array([[ 0,  1,  4,  5],
       [ 8,  9, 12, 13],
       [32, 33, 36, 37],
       [40, 41, 44, 45]])

что если a = np.arange(100).reshape(10, 10)

Ali_Sh 17.05.2022 01:27

Из комментария «По сути, это верхний левый блок 2x2 в каждом макроблоке 4x4» я истолковал вопрос как означающий, что ввод будет массивом, размеры которого делятся на 4. @Akahs, если это не так, не могли бы вы обновить вопрос, чтобы указать это?

Warren Weckesser 17.05.2022 01:34

Да, не беспокойтесь об угловом случае; мы можем предположить, что размер делится на 4. Я просто хотел узнать, как эффективно индексировать этот случай. Это решение кажется рабочим, я пытаюсь его понять.

Akahs 17.05.2022 02:12

Протестировано, чтобы быть самым быстрым среди всех предложенных методов; также он обеспечивает общую основу для перехода к более высокому измерению для своеобразного шага. Преобразование в массив 4D было немного сложным для понимания, но просмотр документации для reshape() несколько помогает.

Akahs 17.05.2022 19:45

Указав массив индексов, поэтому если a.shape[0] % 2 == 0 (четное число):

Примечание:эти методы могут обрабатывать не только когда a.shape[0] % 4 == 0, но и a.shape[0] % 2 == 0 (для всех четных чисел).

Первый метод:

используя предварительное индексирование:

w = 2
ind = np.arange(a.shape[1]).reshape(-1, w)[::2].ravel()    # [0 1 4 5]
b = a[ind[:, None], ind[None, :]]

Второй метод:

от np.delete:

w = 2
ind = np.arange(a.shape[1]).reshape(-1, w)[1::2].ravel()    # [2 3 6 7]
b = np.delete(a, ind, axis=0)
b = np.delete(b, ind, axis=1)

Третий метод:

путем разделения и укладки как:

b = np.asarray(np.hsplit(a, a.shape[0] // 2)[::2])

# [[[ 0  1]       [[ 4  5]
#   [ 8  9]        [12 13]
#   [16 17]        [20 21]
#   [24 25]   ,    [28 29]
#   [32 33]        [36 37]
#   [40 41]        [44 45]
#   [48 49]        [52 53]
#   [56 57]]       [60 61]]]

b = np.asarray(np.vsplit(np.hstack(b), a.shape[0] // 2)[::2])

# [[[ 0  1  4  5]
#   [ 8  9 12 13]]
#         ,
#  [[32 33 36 37]
#   [40 41 44 45]]]

b = np.vstack(b).squeeze()

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