我需要填写图中的矩阵。我的方法是使用非东读的循环。当尺寸很大时,效率也不高。 有没有办法让它更容易阅读,可能更快(比如使用矢量化或某些我不知道的功能?)
# The code is in python, but I am open to R as well.
S=6
p=[0.1,0.3,0.6] # the pi in the figure
# The reason I use loop for p is that it handles a flexible dimension of p
mat = np.zeros((S, S))
p = np.array(p)
for i in range(S):
for j, x in enumerate(p):
if i + j < S-1:
mat[i+j][i] = x
elif i + j == S-1:
mat[S-1][i] = p[j:].sum()
else:
pass
mat.T
答案 0 :(得分:1)
以下是一个示例 - 填写您需要的值(并调整最终列)...
mat <- matrix(0,nrow=10,ncol=10)
diag(mat) <- 1
diag(mat[1:(ncol(mat)-1),-1]) <- 2
diag(mat[1:(ncol(mat)-2),-(1:2)]) <- 3
mat
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 1 2 3 0 0 0 0 0 0 0
[2,] 0 1 2 3 0 0 0 0 0 0
[3,] 0 0 1 2 3 0 0 0 0 0
[4,] 0 0 0 1 2 3 0 0 0 0
[5,] 0 0 0 0 1 2 3 0 0 0
[6,] 0 0 0 0 0 1 2 3 0 0
[7,] 0 0 0 0 0 0 1 2 3 0
[8,] 0 0 0 0 0 0 0 1 2 3
[9,] 0 0 0 0 0 0 0 0 1 2
[10,] 0 0 0 0 0 0 0 0 0 1
答案 1 :(得分:1)
与往常一样,有许多等效的方法来构建矩阵。当我第一次看到它时,我想“哦,它就像是Toeplitz的顶部”,但是对p中的对角线求和也应该有效(注意我已经包含了右下角的变化)。一些谷歌搜索透露了另一种方式,使用scipy.sparse.diags
:
import numpy as np
import scipy.sparse
from scipy.linalg import triu, toeplitz
def build_toep(S, p):
out = triu(toeplitz(p + [0]*(S-len(p))))
out[-2:,-1] = [1 - p[1], 1]
return out
def build_diag(S, p):
out = sum(np.diag([v]*(S-i), i) for i,v in enumerate(p))
out[-2:,-1] = [1 - p[1], 1]
return out
def build_sparse(S, p):
out = scipy.sparse.diags(p, range(len(p)), shape=(S, S)).toarray()
out[-2:,-1] = [1 - p[1], 1]
return out
给出了
In [150]: S, p = 6, [0.1, 0.3, 0.6]
In [151]: build_toep(S, p)
Out[151]:
array([[ 0.1, 0.3, 0.6, 0. , 0. , 0. ],
[ 0. , 0.1, 0.3, 0.6, 0. , 0. ],
[ 0. , 0. , 0.1, 0.3, 0.6, 0. ],
[ 0. , 0. , 0. , 0.1, 0.3, 0.6],
[ 0. , 0. , 0. , 0. , 0.1, 0.7],
[ 0. , 0. , 0. , 0. , 0. , 1. ]])
In [152]: np.allclose(build_toep(S, p), build_diag(S, p))
Out[152]: True
In [153]: np.allclose(build_toep(S, p), build_sparse(S, p))
Out[153]: True