2017-04-01 55 views
0

我需要填充图中的矩阵。我的方法是使用非东方的循环读取。当尺寸较大时,效率也不高。 有什么办法,使其更容易阅读和可能会比较快(?说使用矢量或者一些功能我不知道)更直观的方法来填充对角线向量右边的三个元素

enter image description here

# 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 
+1

[这](http://stackoverflow.com/questions/5852495/how-do-i-find-the -n-numpy-matrix -scalar-product-of-numpy-matrix)将会很有帮助。另外,如果使用'for',则在'for'之后更改黄色部分的值。不需要在内部使用'if'作为',这对于只有两个改变是很麻烦的。 –

回答

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 
+0

我没有想到这是toeplitz的一部分(之前从未听说过),谢谢。 – alphabetagamma

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 
+0

谢谢,分解成三个对角线很聪明。 – alphabetagamma