๐ŸŒ
NumPy
numpy.org โ€บ doc โ€บ stable โ€บ reference โ€บ generated โ€บ numpy.block.html
numpy.block โ€” NumPy v2.5 Manual
The most common use of this function is to build a block matrix: >>> import numpy as np >>> A = np.eye(2) * 2 >>> B = np.eye(3) * 3 >>> np.block([ ... [A, np.zeros((2, 3))], ... [np.ones((3, 2)), B ] ...
๐ŸŒ
w3resource
w3resource.com โ€บ numpy โ€บ manipulation โ€บ block.php
NumPy: numpy.block() function - w3resource
April 24, 2026 - Numpy Array manipulation: numpy.block() is stack arrays in sequence vertically (row wise).
Discussions

python - Better way to create block matrices out of individual blocks in numpy? - Stack Overflow
CopyM=5;N=3; A11=np.random.rand(M,M); A12=np.random.rand(M,N); A21=np.random.rand(N,M); A22=np.random.rand(N,N); I am new to numpy and learning it. I want to create a block matrix in the following manner More on stackoverflow.com
๐ŸŒ stackoverflow.com
python - How can I efficiently process a numpy array in blocks similar to Matlab's blkproc (blockproc) function - Stack Overflow
I'm looking for a good approach for efficiently dividing an image into small regions, processing each region separately, and then re-assembling the results from each process into a single processed... More on stackoverflow.com
๐ŸŒ stackoverflow.com
Is there an efficient way to form this block matrix with numpy or scipy? - Computational Science Stack Exchange
What I am hoping to achieve is an efficient way to generate such a matrix that scales with $N$, and I am able to do it with np.block() and list but it just seems to be not efficient for me. More on scicomp.stackexchange.com
๐ŸŒ scicomp.stackexchange.com
August 13, 2019
Forming a particular (averaged) block matrix with numpy - Computational Science Stack Exchange
Say I have a set of $n \times n$ matrices $A_1, ..., A_m$ as numpy arrays. I'd like to create the block matrix defined below. I'm looking for a clean, elegant, and easy-to-interpret way of doing t... More on scicomp.stackexchange.com
๐ŸŒ scicomp.stackexchange.com
๐ŸŒ
NumPy
numpy.org โ€บ doc โ€บ 2.3 โ€บ reference โ€บ generated โ€บ numpy.block.html
numpy.block โ€” NumPy v2.3 Manual
The most common use of this function is to build a block matrix: >>> import numpy as np >>> A = np.eye(2) * 2 >>> B = np.eye(3) * 3 >>> np.block([ ... [A, np.zeros((2, 3))], ... [np.ones((3, 2)), B ] ...
๐ŸŒ
NumPy
numpy.org โ€บ devdocs โ€บ reference โ€บ generated โ€บ numpy.block.html
numpy.block โ€” NumPy v2.6.dev0 Manual
The most common use of this function is to build a block matrix: >>> import numpy as np >>> A = np.eye(2) * 2 >>> B = np.eye(3) * 3 >>> np.block([ ... [A, np.zeros((2, 3))], ... [np.ones((3, 2)), B ] ...
๐ŸŒ
SciPy
docs.scipy.org โ€บ doc โ€บ numpy-1.13.0 โ€บ reference โ€บ generated โ€บ numpy.block.html
numpy.block โ€” NumPy v1.13 Manual
... Stack arrays in sequence ... array into a list of multiple sub-arrays vertically. ... When called with only scalars, np.block is equivalent to an ndarray call....
๐ŸŒ
TutorialsPoint
tutorialspoint.com โ€บ build-a-block-matrix-in-numpy
Build a block matrix in Numpy
February 17, 2022 - Python TechnologiesDatabasesComputer ... QualityManagement Tutorials View All Categories ... To build a block of matrix, use the numpy.block() method in Python Numpy....
Find elsewhere
๐ŸŒ
SciPy
docs.scipy.org โ€บ doc โ€บ numpy-1.15.0 โ€บ reference โ€บ generated โ€บ numpy.block.html
numpy.block โ€” NumPy v1.15 Manual
... Stack arrays in sequence ... array into a list of multiple sub-arrays vertically. ... When called with only scalars, np.block is equivalent to an ndarray call....
๐ŸŒ
KooR.fr
koor.fr โ€บ Python โ€บ API โ€บ scientist โ€บ numpy โ€บ block.wp
KooR.fr - Fonction block - module numpy - Description de quelques librairies Python
``np.block([[a, b], [c, d]])`` is not restricted to arrays of the form:: AAAbb AAAbb cccDD But is also allowed to produce, for some ``a, b, c, d``:: AAAbb AAAbb cDDDD Since concatenation happens along the last axis first, `block` is *not* capable of producing the following directly:: AAAbb cccbb cccDD Matlab's "square bracket stacking", ``[A, B, ...; p, q, ...]``, is equivalent to ``np.block([[A, B, ...], [p, q, ...]])``. Examples -------- The most common use of this function is to build a block matrix: >>> import numpy as np >>> A = np.eye(2) * 2 >>> B = np.eye(3) * 3 >>> np.block([ ... [A, n
Top answer
1 of 6
26

Here are some examples of a different (loop free) way to work with blocks:

import numpy as np
from numpy.lib.stride_tricks import as_strided as ast

A= np.arange(36).reshape(6, 6)
print A
#[[ 0  1  2  3  4  5]
# [ 6  7  8  9 10 11]
# ...
# [30 31 32 33 34 35]]

# 2x2 block view
B= ast(A, shape= (3, 3, 2, 2), strides= (48, 8, 24, 4))
print B[1, 1]
#[[14 15]
# [20 21]]

# for preserving original shape
B[:, :]= np.dot(B[:, :], np.array([[0, 1], [1, 0]]))
print A
#[[ 1  0  3  2  5  4]
# [ 7  6  9  8 11 10]
# ...
# [31 30 33 32 35 34]]
print B[1, 1]
#[[15 14]
# [21 20]]

# for reducing shape, processing in 3D is enough
C= B.reshape(3, 3, -1)
print C.sum(-1)
#[[ 14  22  30]
# [ 62  70  78]
# [110 118 126]]

So just trying to simply copy the matlab functionality to numpy is not all ways the best way to proceed. Sometimes a 'off the hat' thinking is needed.

Caveat:
In general, implementations based on stride tricks may (but does not necessary need to) suffer some performance penalties. So be prepared to all ways measure your performance. In any case it's wise to first check if the needed functionality (or similar enough, in order to easily adapt for) has all ready been implemented in numpy or scipy.

Update:
Please note that there is no real magic involved here with the strides, so I'll provide a simple function to get a block_view of any suitable 2D numpy-array. So here we go:

from numpy.lib.stride_tricks import as_strided as ast

def block_view(A, block= (3, 3)):
    """Provide a 2D block view to 2D array. No error checking made.
    Therefore meaningful (as implemented) only for blocks strictly
    compatible with the shape of A."""
    # simple shape and strides computations may seem at first strange
    # unless one is able to recognize the 'tuple additions' involved ;-)
    shape= (A.shape[0]/ block[0], A.shape[1]/ block[1])+ block
    strides= (block[0]* A.strides[0], block[1]* A.strides[1])+ A.strides
    return ast(A, shape= shape, strides= strides)

if __name__ == '__main__':
    from numpy import arange
    A= arange(144).reshape(12, 12)
    print block_view(A)[0, 0]
    #[[ 0  1  2]
    # [12 13 14]
    # [24 25 26]]
    print block_view(A, (2, 6))[0, 0]
    #[[ 0  1  2  3  4  5]
    # [12 13 14 15 16 17]]
    print block_view(A, (3, 12))[0, 0]
    #[[ 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]]
2 of 6
11

Process by slices/views. Concatenation is very expensive.

for x in xrange(0, 160, 16):
    for y in xrange(0, 160, 16):
        view = A[x:x+16, y:y+16]
        view[:,:] = fun(view)
Top answer
1 of 2
8

The code proposed by the OP can indeed made be more efficient, mainly by noting the fact that to form the sequence $A^i B$, with $i=0\,\dots,N$ you do not have to compute $A^i$ at each step, but you can exploit the fact that $A^i B = A\,(A^{i-1}B)$, reusing the result of the previous step.

My proposed implementation is

import numpy as np

N = 3
M = 1

A = np.random.random((N, N))
B = np.random.random((N, M))

X = np.zeros((N ** 2, N * M))
rsl = slice(0, N)
X[rsl, :M] = B
for i in range(1, N):
    rsl_p, rsl = rsl, slice(i * N, (i + 1) * N)
    X[rsl, :M] = A @ X[rsl_p, :M]
    X[rsl, M : (i + 1) * M] = X[rsl_p, : i * M]

This question is more related to programming that computational science, so I add some general remarks, useful for a novice programmer.

  1. never blindly translate mathematical expressions into code: think algorithmically.

    X = np.linalg.matrix_power(A,i)@B 
    

    is much slower than

    X=B; 
    for j in range(i): X = A*X
    

    if $M \ll N$

    (exercise: compute operation count for both code fragments).

  2. whenever possible reuse previous calculations.

  3. pre-allocate output matrices, and do not store intermediate results in temp. matrices

2 of 2
2

If you need to explicitly construct the entire matrix, then Stefano M's answer is your best bet. If, however, you don't really need the whole matrix, but just need to be able to perform a matrix-vector-product (MVP), then you might want to consider the following approach. Based on your comments it's unclear to me if this helps you, and I realize this doesn't technically answer your question, but I thought I'd post it just in case.

Suppose you want to calculate the MVP:

$\left( \begin{array}{c}y_1 \\ y_2 \\ \vdots \\ y_N \end{array} \right) = \left( \begin{array}{cccc} B & 0 & ... & 0 \\ A B & B & ... & 0 \\ \vdots & \vdots & \ddots & \vdots \\ A^{N-1} B & A^{N-2} B & ... & B \end{array} \right) \left( \begin{array}{c}x_1 \\ x_2 \\ \vdots \\ x_N \end{array} \right)$

where $x_i$'s are size $Mx1$ and known and we want to calculate $y_i$'s which are size $Nx1$ and unknown. This can be expressed block-by-block as

$\begin{array}{lll} y_i & = & \sum\limits_{j=1}^{i} A^{i-j} B x_j\\ & = & B x_i + \sum\limits_{j=1}^{i-1} A^{i-j} B x_j \\ & = & B x_i + A \sum\limits_{j=1}^{i-1} A^{(i-1)-j} B x_j \\ & = & B x_i + A y_{i-1}\\ \end{array}$

for $i=1,2,...,N$. (The last step works if we assume $y_0 \equiv \mathbf{0}^{[N \times 1]}$.)

This should be much faster than using the full dense matrix.

Example Python code:

import numpy as np

def mvp(A,B,x):

    n=A.shape[0]
    m=B.shape[1]

    # assume that x is 1D array of size [n*m]

    y=np.zeros( (n*n) )

    y[:n] = B @ x[:m]
    for i in range(1,n):
        y[i*n:(i+1)*n] = B @ x[i*m:(i+1)*m] + A @ y[(i-1)*n:i*n]

    return y

N = 3
M = 1

A = np.random.random((N, N))
B = np.random.random((N, M))
x=np.random.random( (N*M) )

y=mvp(A,B,x)

๐ŸŒ
Dustin
dkenefake.github.io โ€บ blog โ€บ Numpy_Block
Numpy Block is slow ยท Dustin
November 30, 2020 - import numpy row = numpy.array([[i] for i in range(10)]) row_blocking = [row for i in range(1000)] %timeit dustin_block(row_blocking) %timeit numpy.block(row_blocking) brick = numpy.eye(5) row = [brick for i in range(10)] row_blocking = [row for i in range(10)] %timeit dustin_block(row_blocking) %timeit numpy.block(row_blocking)
๐ŸŒ
Reddit
reddit.com โ€บ r/learnpython โ€บ efficiently divide numpy array into blocks sized y x y and apply function to each block
r/learnpython on Reddit: Efficiently divide numpy array into blocks sized Y x Y and apply function to each block
May 23, 2021 -

Hey,

I have the following problem: I have a 2D numpy array (256 x 256 shape) and I want to divide it into equally sized blocks (for example 8 x 8 elements blocks) and apply a custom function to each block (which should reflect changes made in this function onto the original array).

What I first tried was simply (I know basically one should never do this) looping with a double for loop over the array (with step size being the blocks shape) and applying the function on each block. This worked, but it was really, really slow and barely worked for smaller block sizes like 2 x 2.

Next, I used the following (which is basically the view_as_blocks function from skimage.util.shape.

from numpy.lib.stride_tricks import as_strided

def chunk(arr_in: np.ndarray, block_shape:tuple) -> np.ndarray:     
    block_shape = np.array(block_shape)
    arr_shape = np.array(arr_in.shape)
    new_shape = tuple(arr_shape // block_shape) + tuple(block_shape)
    new_strides = tuple(arr_in.strides * block_shape) + arr_in.strides
    arr_out = as_strided(arr_in, shape=new_shape, strides=new_strides)
    return arr_out

And then looped through the resulting blocks one by one and assembling it into a new array like this:

def my_main_fun() -> None:
    # the blocks   
    s = chunk(img, (chunk_size, chunk_size))
    # the new array
    t = np.zeros_like(img)
    for i in range(s.shape[0]):
        for j in range(s.shape[1]):
            o_i = i * chunk_size
            o_j = j * chunk_size 
            _, vals = myCustomFunction(s[i][j])
            t[o_i:o_i + chunk_size, o_j:o_j + chunk_size] = vals

This was faster, but it also takes quite a lot time (I assume due to the double for loop in the reassembling (second) function).

Now my question: How can I do this much more efficiently?

Note that its guaranteed that the block shape (which is always a square) is evenly divisible by the arrays shape and I only care about 2D arrays for now.

Many thanks in advance ;)