Как объединить несколько матриц с разными формами в одну диагональную матрицу и pad 0 для недиагональных элементов?

#python #matrix

#python #матрица

Вопрос:

Если у меня есть эти матрицы:

 A = [[1,2,3],[4,5,6],[7,8,9]]   
B = [[0,0],[1,1]]
C = [[0,1,1],[1,1,0],[1,0,1],[0,0,0]]
  

как я могу объединить их, чтобы получить такую матрицу?

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

Я ищу общее решение, которое не ограничивается, скажем, только 3 входными матрицами.

Комментарии:

1. Пожалуйста, определите «соединение» и «диагональ» в вашем контексте.

2. Приведенный пример говорит сам за себя. A, B и C являются входными матрицами, а выходные D = [A00 0B0 00C] данные содержат элементы A, B, C, появляющиеся по диагонали D, а недиагональные элементы равны 0. Вы ищете математическое описание для «соединения» или «диагонали»?

Ответ №1:

Исключительно в качестве академического упражнения….

 A = [[1,2,3],[4,5,6],[7,8,9]]   
B = [[0,0],[1,1]]
C = [[0,1,1],[1,1,0],[1,0,1],[0,0,0]]

data = [A,B,C] # merge for iteration

rowlen = sum(len(x[0]) for x in data)  # full row length

mtx = []

col = 0
for d in data: # each data list (A/B/C)
   for d2 in d:  # each sublist
      mtx.append([0]*col   d2   [0]*(rowlen-col-len(d2))) # data plus '0' buffers
   col  = len(d[0])  # shift column 

print(mtx)
  

Вывод

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

Комментарии:

1. Спасибо. Есть ли способ избежать использования for циклов для увеличения скорости?

2. Здесь было бы сложно реализовать понимание списка, и любой прирост скорости был бы минимальным.

Ответ №2:

Похоже, что это можно просто сделать block_diag с помощью scipy:

 from scipy.linalg import block_diag
data = [A,B,C]
block_diag(*data)
  

вывод:

 array([[1, 2, 3, 0, 0, 0, 0, 0],
       [4, 5, 6, 0, 0, 0, 0, 0],
       [7, 8, 9, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 1, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 1, 1],
       [0, 0, 0, 0, 0, 1, 1, 0],
       [0, 0, 0, 0, 0, 1, 0, 1],
       [0, 0, 0, 0, 0, 0, 0, 0]])