Skip to content Skip to sidebar Skip to footer

What Is The Best Way To Create A Block Matrix Form A Row Vector?

I have the following numpy row matrix. X = np.array([1,2,3]) I want to create a block matrix as follows: 1 0 0 2 1 0 3 2 1 0 3 2 0 0 3 How can I do this using numpy?

Solution 1:

If you read the desired output matrix top-down, then left-right, you see the pattern 1,2,3, 0,0,0, 1,2,3, 0,0,0, 1,2,3. You can use that pattern to easily create a linear array, and then reshape it into the two-dimensional form:

import numpy as np
X = np.array([1,2,3])
N = len(X)
zeros = np.zeros_like(X)
m = np.hstack((np.tile(np.hstack((X,zeros)),N-1),X)).reshape(N,-1).T
print m

gives

[[1 0 0][2 1 0][3 2 1][0 3 2][0 0 3]]

Solution 2:

Approach #1 : Using np.lib.stride_tricks.as_strided -

from numpy.lib.stride_tricks import as_strided as strided

defzeropad_arr_v1(X):
    n = len(X)
    z = np.zeros(len(X)-1,dtype=X.dtype)
    X_ext = np.concatenate(( z, X, z))

    s = X_ext.strides[0]
    return strided(X_ext[n-1:], (2*n-1,n), (s,-s), writeable=False)

Note that this would create a read-only output. If you need to write into later on, simply make a copy by appending .copy() at the end.

Approach #2 : Using concatenation with zeros and then clipping/slicing -

def zeropad_arr_v2(X):
    n = len(X)
    X_ext = np.concatenate((X, np.zeros(n,dtype=X.dtype)))
    return np.tile(X_ext, n)[:-n].reshape(-1,n,order='F')

Approach #1 being a strides-based method should be very efficient on performance.

Sample runs -

In [559]: X = np.array([1,2,3])

In [560]: zeropad_arr_v1(X)
Out[560]: 
array([[1, 0, 0],
       [2, 1, 0],
       [3, 2, 1],
       [0, 3, 2],
       [0, 0, 3]])

In [561]: zeropad_arr_v2(X)
Out[561]: 
array([[1, 0, 0],
       [2, 1, 0],
       [3, 2, 1],
       [0, 3, 2],
       [0, 0, 3]])

Runtime test

In [611]:X=np.random.randint(0,9,(1000))# Approach #1 (read-only)In [612]:%timeitzeropad_arr_v1(X)100000loops,best of 3:8.74µsperloop# Approach #1 (writable)In [613]:%timeitzeropad_arr_v1(X).copy()1000 loops,best of 3:1.05msperloop# Approach #2In [614]:%timeitzeropad_arr_v2(X)1000 loops,best of 3:705µsperloop# @user8153's solutionIn [615]:%timeithstack_app(X)100loops,best of 3:2.26msperloop

Solution 3:

An other writable solution :

def block(X):
   n=X.size
   zeros=np.zeros((2*n-1,n),X.dtype)
   zeros[::2]=X
   return zeros.reshape(n,-1).T

try :

In [2]: %timeit block(X)
600 µs ± 33 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Post a Comment for "What Is The Best Way To Create A Block Matrix Form A Row Vector?"