2

l have K (let K here be 7) distincts matrices of dimension (50,50). I would like to create a new matrix L by filling it in diagonal with the K matrices. Hence L is of dimension (50*K,50*K).

What l have tried ?

K1=np.random.random((50,50)) 
N,N=K1.shape
K=7
out=np.zeros((K,N,K,N),K1.dtype)
np.einsum('ijik->ijk', out)[...] = K1
L=out.reshape(K*N, K*N) # L is of dimension (50*7,50*7)=(350,350)

Its indeed creating a new matrix L by stacking K1 seven times within its diagonal. However, l would like to stack respectively K1,K2,K3,K5,K6,K7 rather than K1 seven times.

Inputs :

    K1=np.random.random((50,50)) 
    K2=np.random.random((50,50)) 
    K3=np.random.random((50,50)) 
    K4=np.random.random((50,50)) 
    K5=np.random.random((50,50)) 
    K6=np.random.random((50,50)) 
    K7=np.random.random((50,50)) 

    L=np.zeros((50*7,50*7))#

Expected outputs :

L[:50,:50]=K1
L[50:100,50:100]=K2
L[100:150,100:50]=K3
L[150:200,150:200]=K4
L[200:250,200:250]=K5
L[250:300,250:300]=K6
L[300:350,300:350]=K7
Taylor
  • 127
  • 1
  • 10

2 Answers2

2

You could try scipy.linalg.block_diag. If you look at the source, this function basically just loops over the given blocks the way you have written as your output. It can be used like:

K1=np.random.random((50,50)) 
K2=np.random.random((50,50)) 
K3=np.random.random((50,50)) 
K4=np.random.random((50,50)) 
K5=np.random.random((50,50)) 
K6=np.random.random((50,50)) 
K7=np.random.random((50,50)) 

L=sp.linalg.block_diag(K1,K2,K3,K4,K5,K6,K7)

If you have your K as a ndarray of shape (7,50,50) you can unpack it directly like:

K=np.random.random((7,50,50))

L=sp.linalg.block_diag(*K)

If you don't want to import scipy, you can always just write a simple loop to do what you have written for the expected output.

overfull hbox
  • 747
  • 3
  • 10
1

Here is a way to do that with NumPy:

import numpy as np

def put_in_diagonals(a):
    n, rows, cols = a.shape
    b = np.zeros((n * rows, n * cols), dtype=a.dtype)
    a2 = a.reshape(-1, cols)
    ii, jj = np.indices(a2.shape)
    jj += (ii // rows) * cols
    b[ii, jj] = a2
    return b

# Test
a = np.arange(24).reshape(4, 2, 3)
print(put_in_diagonals(a))

Output:

[[ 0  1  2  0  0  0  0  0  0  0  0  0]
 [ 3  4  5  0  0  0  0  0  0  0  0  0]
 [ 0  0  0  6  7  8  0  0  0  0  0  0]
 [ 0  0  0  9 10 11  0  0  0  0  0  0]
 [ 0  0  0  0  0  0 12 13 14  0  0  0]
 [ 0  0  0  0  0  0 15 16 17  0  0  0]
 [ 0  0  0  0  0  0  0  0  0 18 19 20]
 [ 0  0  0  0  0  0  0  0  0 21 22 23]]
jdehesa
  • 58,456
  • 7
  • 77
  • 121