Are there any convenience utilities for doing blockwise operations on Numpy arrays?
I am thinking of operations like Ising spin renormalization where you divide a ma
This can also be done with simple reshaping. The idea is to interleave the number of blocks and the block size for each dimension.
For example, with an array of shape (6, 12, 20)
, and targeting a block size of (2, 3, 4)
, reshaping to (3, 2, 4, 3, 5, 4)
will do.
After the reshaping, the block position and the block size axes are alternating:
but they can easily be rearranged with np.transpose()
.
A 2D example follows:
import numpy as np
block_shape = 2, 2
repeats = 3, 3
m = repeats[0] * block_shape[0]
n = repeats[1] * block_shape[1]
arr = np.arange((m * n)).reshape((m, n))
print(arr)
# [[ 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]]
block_shape = tuple(x for nm in zip(repeats, block_shape) for x in nm)
# (3, 2, 3, 2)
repeat_indexes = tuple(range(0, len(block_shape), 2))
# 0, 2
block_indexes = tuple(range(1, len(block_shape), 2))
# 1, 3
block_arr = arr.reshape(block_shape).transpose(repeat_indexes + block_indexes)
print(block_arr)
# [[[[ 0 1]
# [ 6 7]]
# [[ 2 3]
# [ 8 9]]
# [[ 4 5]
# [10 11]]]
# [[[12 13]
# [18 19]]
# [[14 15]
# [20 21]]
# [[16 17]
# [22 23]]]
# [[[24 25]
# [30 31]]
# [[26 27]
# [32 33]]
# [[28 29]
# [34 35]]]]