Скажем, у меня есть массив, который выглядит как
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))
Но мне интересно, есть ли более чистый способ сделать это.
Вот один из способов сделать это:
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]])
Из комментария «По сути, это верхний левый блок 2x2 в каждом макроблоке 4x4» я истолковал вопрос как означающий, что ввод будет массивом, размеры которого делятся на 4. @Akahs, если это не так, не могли бы вы обновить вопрос, чтобы указать это?
Да, не беспокойтесь об угловом случае; мы можем предположить, что размер делится на 4. Я просто хотел узнать, как эффективно индексировать этот случай. Это решение кажется рабочим, я пытаюсь его понять.
Протестировано, чтобы быть самым быстрым среди всех предложенных методов; также он обеспечивает общую основу для перехода к более высокому измерению для своеобразного шага. Преобразование в массив 4D было немного сложным для понимания, но просмотр документации для reshape()
несколько помогает.
Указав массив индексов, поэтому если 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()
что если
a = np.arange(100).reshape(10, 10)