如何将矩阵打包到单元格中,然后形成 python 的对角矩阵
How to pack matrices into cells and then form a diagonal matrix with python
我需要根据重复 3 次的 X 矩阵在 python 中创建对角矩阵。在 matlab 中,我按以下方式进行:
X=[1 2 3;
4 5 6;
7 8 9]
for i=1:1:3
Brep{i}=X;
end
Mdiag=blkdiag(Brep{:})
Mdiag =
1 2 3 0 0 0 0 0 0
4 5 6 0 0 0 0 0 0
7 8 9 0 0 0 0 0 0
0 0 0 1 2 3 0 0 0
0 0 0 4 5 6 0 0 0
0 0 0 7 8 9 0 0 0
0 0 0 0 0 0 1 2 3
0 0 0 0 0 0 4 5 6
0 0 0 0 0 0 7 8 9
但我不知道如何在 Pyhton 中执行此操作。
如有任何帮助,我将不胜感激。
-------------------------------- 答案:---------- --------------------------
考虑到 Fabrizio Bernini 提供的答案,我修改了他的代码以使其更通用。代码现在可以在对角线上重复矩阵 X(任意维度)n 次。例如:
import numpy as np
n=5
x = np.array([[1, 2, 3],[4, 5, 6],[7, 8, 9]])
Mdiag = np.zeros((n*x.shape[0], n*x.shape[1]))
for i in range(n):
Mdiag[x.shape[0]*i:x.shape[0]*i+x.shape[0],x.shape[1]*i:x.shape[1]*i+x.shape[1]]= x
Mdiag =[1., 2., 3., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[4., 5., 6., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[7., 8., 9., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 1., 2., 3., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 4., 5., 6., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 7., 8., 9., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 2., 3., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 4., 5., 6., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 7., 8., 9., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 2., 3., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 4., 5., 6., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 7., 8., 9., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 2., 3.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 4., 5., 6.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 7., 8., 9.]
感谢大家提供的答案。
试试这个代码。
import numpy as np
X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
M = np.zeros(shape = (9, 9))
for i in range(3):
M[3*i:3*(i+1), 3*i:3*(i+1)] = X
一种方法是创建一个大的零矩阵并直接将 x
粘贴到对角线位置:
N = 3
y = np.zeros((x.shape[0] * N, x.shape[1] * N))
for i in range(N):
y[i * x.shape[0] : (i + 1) * x.shape[0],
i * x.shape[1] : (i + 1) * x.shape[1]] = x
另一种解决方案:创建一条 x
的水平“带”,并根据需要创建尽可能多的 0。然后堆叠三份该腰带,移位:
belt = np.hstack([x, np.zeros((x.shape[0], (x.shape[1] - 1) * N))])
np.vstack([np.roll(belt, i) for i in range(0, x.shape[0] * N, x.shape[0])])
你可以使用 scipy.linalg.block_diag
:
from scipy.linalg import block_diag
X=[[1, 2, 3],
[4,5,6],
[7, 8, 9]]
block_diag(X, X, X)
输出:
array([[1, 2, 3, 0, 0, 0, 0, 0, 0],
[4, 5, 6, 0, 0, 0, 0, 0, 0],
[7, 8, 9, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 2, 3, 0, 0, 0],
[0, 0, 0, 4, 5, 6, 0, 0, 0],
[0, 0, 0, 7, 8, 9, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 2, 3],
[0, 0, 0, 0, 0, 0, 4, 5, 6],
[0, 0, 0, 0, 0, 0, 7, 8, 9]], dtype=int32)
另一个选项,使用 np.bmat
, np.asmatrix
and np.asarray
,可能是这样的:
import numpy as np
X=np.asmatrix([[1, 2, 3],
[4,5,6],
[7, 8, 9]])
y = np.asmatrix(np.zeros((3, 3)))
r=np.asarray(np.bmat('X, y, y; y, X, y; y, y, X'))
print(r)
您没有标记任何“高级”模块(scipy, numpy,...)所以我们开始吧:
您可以自己创建一个函数来执行此操作。矩阵在 python 中显示为列表的列表(除非你进入 numpy 等):
def diag_size(what, size = 4):
"""Create a diagonal matrix of size len(what)*size where the list of list
'what' is on the diagonal of the embiggended result"""
rv = [[]]
s = len(what) # quadratic => len(what) == len(what[0])
for row in range(size*s):
for col in range(size*s):
if row//s == col//s:
rv[-1].append(base[row%s][col%s])
else:
rv[-1].append(0)
rv.append([])
return rv[:-1]
n = 3 # size of the initial "matrix"
# create base case
base = [list(range(i+1,i+n+1)) for i in range(0,n*n,n)]
# create the diagonal one
print(*diag_size(base),sep="\n")
输出:
# with size=4 you get a 4 wide diagonal matrix
[1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 4, 5, 6, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 4, 5, 6, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 7, 8, 9, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9]
你可以使用 numpy 做这样的事情:
import numpy
x = np.array([[1, 2, 3],[4, 5, 6],[7, 8, 9]])
Mdiag = np.zeros((9, 9))
for i in range(3):
Mdiag[3*i:3*i+3, 3*i:3*i+3] = x
您还可以使用 np.reshape:
生成初始矩阵
x = np.arange(1, 10)
x = x.reshape((3, 3))
更一般地说,如果您有一个 nxn 子矩阵并想要创建一个 MxM 对角分块矩阵,其中 M = c*n,您可以这样做:
import numpy
x = ... define here your nxn matrix
Mdiag = np.zeros((M, M))
for i in range(n):
Mdiag[n*i:n*i+n, n*i:n*i+n] = x
有用于复制块矩阵和生成块矩阵的 numpy 内置函数,但我不知道有人只用一个命令生成对角块矩阵。
另请参阅此以供参考:
[1]: https://numpy.org/doc/stable/reference/generated/numpy.matlib.repmat.html#numpy.matlib.repmat 和
[2]: https://numpy.org/doc/stable/reference/generated/numpy.block.html?highlight=block%20matrix
我需要根据重复 3 次的 X 矩阵在 python 中创建对角矩阵。在 matlab 中,我按以下方式进行:
X=[1 2 3;
4 5 6;
7 8 9]
for i=1:1:3
Brep{i}=X;
end
Mdiag=blkdiag(Brep{:})
Mdiag =
1 2 3 0 0 0 0 0 0
4 5 6 0 0 0 0 0 0
7 8 9 0 0 0 0 0 0
0 0 0 1 2 3 0 0 0
0 0 0 4 5 6 0 0 0
0 0 0 7 8 9 0 0 0
0 0 0 0 0 0 1 2 3
0 0 0 0 0 0 4 5 6
0 0 0 0 0 0 7 8 9
但我不知道如何在 Pyhton 中执行此操作。
如有任何帮助,我将不胜感激。
-------------------------------- 答案:---------- --------------------------
考虑到 Fabrizio Bernini 提供的答案,我修改了他的代码以使其更通用。代码现在可以在对角线上重复矩阵 X(任意维度)n 次。例如:
import numpy as np
n=5
x = np.array([[1, 2, 3],[4, 5, 6],[7, 8, 9]])
Mdiag = np.zeros((n*x.shape[0], n*x.shape[1]))
for i in range(n):
Mdiag[x.shape[0]*i:x.shape[0]*i+x.shape[0],x.shape[1]*i:x.shape[1]*i+x.shape[1]]= x
Mdiag =[1., 2., 3., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[4., 5., 6., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[7., 8., 9., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 1., 2., 3., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 4., 5., 6., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 7., 8., 9., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 2., 3., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 4., 5., 6., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 7., 8., 9., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 2., 3., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 4., 5., 6., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 7., 8., 9., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 2., 3.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 4., 5., 6.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 7., 8., 9.]
感谢大家提供的答案。
试试这个代码。
import numpy as np
X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
M = np.zeros(shape = (9, 9))
for i in range(3):
M[3*i:3*(i+1), 3*i:3*(i+1)] = X
一种方法是创建一个大的零矩阵并直接将 x
粘贴到对角线位置:
N = 3
y = np.zeros((x.shape[0] * N, x.shape[1] * N))
for i in range(N):
y[i * x.shape[0] : (i + 1) * x.shape[0],
i * x.shape[1] : (i + 1) * x.shape[1]] = x
另一种解决方案:创建一条 x
的水平“带”,并根据需要创建尽可能多的 0。然后堆叠三份该腰带,移位:
belt = np.hstack([x, np.zeros((x.shape[0], (x.shape[1] - 1) * N))])
np.vstack([np.roll(belt, i) for i in range(0, x.shape[0] * N, x.shape[0])])
你可以使用 scipy.linalg.block_diag
:
from scipy.linalg import block_diag
X=[[1, 2, 3],
[4,5,6],
[7, 8, 9]]
block_diag(X, X, X)
输出:
array([[1, 2, 3, 0, 0, 0, 0, 0, 0],
[4, 5, 6, 0, 0, 0, 0, 0, 0],
[7, 8, 9, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 2, 3, 0, 0, 0],
[0, 0, 0, 4, 5, 6, 0, 0, 0],
[0, 0, 0, 7, 8, 9, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 2, 3],
[0, 0, 0, 0, 0, 0, 4, 5, 6],
[0, 0, 0, 0, 0, 0, 7, 8, 9]], dtype=int32)
另一个选项,使用 np.bmat
, np.asmatrix
and np.asarray
,可能是这样的:
import numpy as np
X=np.asmatrix([[1, 2, 3],
[4,5,6],
[7, 8, 9]])
y = np.asmatrix(np.zeros((3, 3)))
r=np.asarray(np.bmat('X, y, y; y, X, y; y, y, X'))
print(r)
您没有标记任何“高级”模块(scipy, numpy,...)所以我们开始吧:
您可以自己创建一个函数来执行此操作。矩阵在 python 中显示为列表的列表(除非你进入 numpy 等):
def diag_size(what, size = 4):
"""Create a diagonal matrix of size len(what)*size where the list of list
'what' is on the diagonal of the embiggended result"""
rv = [[]]
s = len(what) # quadratic => len(what) == len(what[0])
for row in range(size*s):
for col in range(size*s):
if row//s == col//s:
rv[-1].append(base[row%s][col%s])
else:
rv[-1].append(0)
rv.append([])
return rv[:-1]
n = 3 # size of the initial "matrix"
# create base case
base = [list(range(i+1,i+n+1)) for i in range(0,n*n,n)]
# create the diagonal one
print(*diag_size(base),sep="\n")
输出:
# with size=4 you get a 4 wide diagonal matrix
[1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 4, 5, 6, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 4, 5, 6, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 7, 8, 9, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9]
你可以使用 numpy 做这样的事情:
import numpy
x = np.array([[1, 2, 3],[4, 5, 6],[7, 8, 9]])
Mdiag = np.zeros((9, 9))
for i in range(3):
Mdiag[3*i:3*i+3, 3*i:3*i+3] = x
您还可以使用 np.reshape:
生成初始矩阵x = np.arange(1, 10)
x = x.reshape((3, 3))
更一般地说,如果您有一个 nxn 子矩阵并想要创建一个 MxM 对角分块矩阵,其中 M = c*n,您可以这样做:
import numpy
x = ... define here your nxn matrix
Mdiag = np.zeros((M, M))
for i in range(n):
Mdiag[n*i:n*i+n, n*i:n*i+n] = x
有用于复制块矩阵和生成块矩阵的 numpy 内置函数,但我不知道有人只用一个命令生成对角块矩阵。 另请参阅此以供参考:
[1]: https://numpy.org/doc/stable/reference/generated/numpy.matlib.repmat.html#numpy.matlib.repmat 和 [2]: https://numpy.org/doc/stable/reference/generated/numpy.block.html?highlight=block%20matrix