Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Numpy Matrix tiling and multiplication combination

I'm looking for a function capable of taking a m x n array, which repeats each row n times over a identity-like grid of m size.

For demo:

input = [[a1, b1, c1],
         [a2, b2, c2]]

output = [[a1, b1, c1,  0,  0,  0],
          [a1, b1, c1,  0,  0,  0],
          [a1, b1, c1,  0,  0,  0],
          [ 0,  0,  0, a2, b2, c2],
          [ 0,  0,  0, a2, b2, c2],
          [ 0,  0,  0, a2, b2, c2]]

Last time I asked something similar I was told of the Kronecker product, is there some similar function?

like image 236
AReubens Avatar asked Sep 01 '25 03:09

AReubens


2 Answers

While looking similar, it appears to me that the given problem cannot be solved using a Kronecker product: with the latter, you could only manage to get repetitions of your complete input matrix as blocks of the result matrix.

I stand corrected: For a solution that employs the Kronecker product, see @ThomasIsCoding's answer.

In any case, what you need is the individual rows, repeated, as blocks of the result matrix. So that is what the code below does: it constructs a block matrix from the rows, using scipy.linalg.block_diag(), then repeats them as required, using numpy.repeat(). Note that block_diag() expects individual blocks as individual arguments, which is why a is unpacked with the * prefix.

import numpy as np
import scipy

a = np.asarray([[11, 21, 31], [21, 22, 32], [31, 32, 33]])
print(a)
# [[11 21 31]
#  [21 22 32]
#  [31 32 33]]

blocked = scipy.linalg.block_diag(*a)
print(blocked)
# [[11 21 31  0  0  0  0  0  0]
#  [ 0  0  0 21 22 32  0  0  0]
#  [ 0  0  0  0  0  0 31 32 33]]

result = np.repeat(blocked, a.shape[1], axis=0)
print(result)
# [[11 21 31  0  0  0  0  0  0]
#  [11 21 31  0  0  0  0  0  0]
#  [11 21 31  0  0  0  0  0  0]
#  [ 0  0  0 21 22 32  0  0  0]
#  [ 0  0  0 21 22 32  0  0  0]
#  [ 0  0  0 21 22 32  0  0  0]
#  [ 0  0  0  0  0  0 31 32 33]
#  [ 0  0  0  0  0  0 31 32 33]
#  [ 0  0  0  0  0  0 31 32 33]]
like image 159
simon Avatar answered Sep 02 '25 16:09

simon


Here is another option, using np.kron

r,c = a.shape
u = np.kron(np.kron(np.ones((1, r)), a), np.ones((c, 1)))
idx = np.repeat(np.arange(r)[:,None], c, axis=0)
u*(idx==idx.T)

which gives

array([[11., 21., 31.,  0.,  0.,  0.,  0.,  0.,  0.],
       [11., 21., 31.,  0.,  0.,  0.,  0.,  0.,  0.],
       [11., 21., 31.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0., 21., 22., 32.,  0.,  0.,  0.],
       [ 0.,  0.,  0., 21., 22., 32.,  0.,  0.,  0.],
       [ 0.,  0.,  0., 21., 22., 32.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0., 31., 32., 33.],
       [ 0.,  0.,  0.,  0.,  0.,  0., 31., 32., 33.],
       [ 0.,  0.,  0.,  0.,  0.,  0., 31., 32., 33.]])
like image 33
ThomasIsCoding Avatar answered Sep 02 '25 16:09

ThomasIsCoding