Francesco Di Lauro
Francesco Di Lauro

Reputation: 630

How to create a bigger matrix from a smaller one according to a rule

I have a matrix, say 3 x 3

x= np.arange(0,9,1).reshape((3,3))

and I want to get a bigger matrix (9x9) built according to the following simple rule:

the first three rows of the new matrix are identical, and made from the first row of x and zeros to the end.

The second three rows are identical and are made from the second row of x by three 0s, then x, then 0s to the end of the row, and so on. Something like this.

0 1 2 0 0 0 0 0 0
0 1 2 0 0 0 0 0 0
0 1 2 0 0 0 0 0 0
0 0 0 3 4 5 0 0 0
0 0 0 3 4 5 0 0 0
0 0 0 3 4 5 0 0 0
0 0 0 0 0 0 6 7 8  
0 0 0 0 0 0 6 7 8
0 0 0 0 0 0 6 7 8

Is there a way to do it in a pythonic way? I have tried to see if by using numpy.kron / numpy.repeat but I don't think this is the way.

In particular I thought first to get a matrix 9*3 by

x=np.repeat(x,3)

and then try to complete it with zeros by using np.kron, but it did not work.

Upvotes: 0

Views: 67

Answers (2)

Karol Żak
Karol Żak

Reputation: 2406

Not sure how pythonic it is but my idea is to use list comprehension to iterate through each row and np.pad it based on changing parameters:

import numpy as np

x = np.arange(0,9,1).reshape((3,3))

a = x.shape[1]  # length of original rows | you can hardcode to 3
b = x.shape[0]*a - a  # number of cells you will pad each row with | you can hardcode it to 6
repeat = 3 # how many times each row should be repeated

x_padded = [np.pad(row, (i*a, b-i*a)) for i, row in enumerate(x)]
x_out = np.repeat(x_padded, repeat, axis=0)
print(x_out)

Output:

[[0 1 2 0 0 0 0 0 0]
 [0 1 2 0 0 0 0 0 0]
 [0 1 2 0 0 0 0 0 0]
 [0 0 0 3 4 5 0 0 0]
 [0 0 0 3 4 5 0 0 0]
 [0 0 0 3 4 5 0 0 0]
 [0 0 0 0 0 0 6 7 8]
 [0 0 0 0 0 0 6 7 8]
 [0 0 0 0 0 0 6 7 8]]

Upvotes: 1

V. Ayrat
V. Ayrat

Reputation: 2719

You can use block_diag from scipy.linalg.

"""
>>> print(answer)
[[0 1 2 0 0 0 0 0 0]
 [0 1 2 0 0 0 0 0 0]
 [0 1 2 0 0 0 0 0 0]
 [0 0 0 3 4 5 0 0 0]
 [0 0 0 3 4 5 0 0 0]
 [0 0 0 3 4 5 0 0 0]
 [0 0 0 0 0 0 6 7 8]
 [0 0 0 0 0 0 6 7 8]
 [0 0 0 0 0 0 6 7 8]]
"""
from scipy.linalg import block_diag
import numpy as np

x = np.arange(9).reshape(3, 3)
answer = block_diag(*np.array_split(x.repeat(3, axis=0), 3))

Upvotes: 2

Related Questions