如何访问矩阵的对角线并更改值?

时间:2012-11-27 22:04:16

标签: matlab matrix octave

我有8x8矩阵,其中我有15个对角线。左上角“对角线1”和下方 右角“对角线15”。我想将{9,10,11,12,13,14,15}或{5,6,7,8,9,10,11,12,13,14,15}等特定对角线归零。 。有人请给我解决方案吗?

7 个答案:

答案 0 :(得分:1)

我相信你可以使用:

M = M - diag(diag(M,k),k);

其中k为主对角线为0,低对角线为负(最高为-7),上对角线为正(最多7)。

编辑:我的不好,这只是你所选择的对角线之一。您可以对要清零的所有对角线重复此过程,但这可能不是最佳:

for k=[9 10 11 12 13 14 15]
    M = M - diag(diag(M,k-length(M)),k-length(M));
end

答案 1 :(得分:0)

我不确定我是否理解你的问题。您是否尝试将主对角线上的某些元素归零,或者您是否尝试将整个对角线归零?无论哪种方式,您都可以使用Matlab的“diag”函数。

如果你想将主对角线上的某些元素归零,你可以使用类似的东西:

% A is a 15 x 15 matrix, want to zero out {1,2,3,8}th elements on the diagonal
d = diag(A); % diagonal elements of A
d([4:7 9:15]) = 0; % zero out the elements you want to KEEP
A = A - diag(d); % diag d is a diagonal matrix with d on the main diagonal

但是使用for循环会更容易:

for i=[1,2,3,8]
A(i,i) = 0;
end

将A的第n个对角线归零实际上更容易:

假设您想要将第3个对角线归零,您会这样做:     A = A - 诊断(诊断(A,3),3);

答案 2 :(得分:0)

我认为我的对角线是另一种方式,但你应该明白这一点。

Python代码:

import numpy as np

matrix = np.ones((8,8))

print "matrix = \n", matrix

# Need to map "diagnals" to starting row & offset, this is for 8x8

start_map = {}

start_map[ 0] = (0, 7)
start_map[ 1] = (0, 6)
start_map[ 2] = (0, 5)
start_map[ 3] = (0, 4)
start_map[ 4] = (0, 3)
start_map[ 5] = (0, 2)
start_map[ 6] = (0, 1)
start_map[ 7] = (0, 0)
start_map[ 8] = (1, 0)
start_map[ 9] = (2, 0)
start_map[10] = (3, 0)
start_map[11] = (4, 0)
start_map[12] = (5, 0)
start_map[13] = (6, 0)
start_map[14] = (7, 0)

# Zero out selected "diagnal"

M, N = matrix.shape

for i in xrange(15):

    new_matrix = np.array(matrix)

    m, n = start_map[i]

    while m < M and n < N:

        new_matrix[m, n] = 0.0

        m += 1
        n += 1

    print "'diag' = %d\n" % i, new_matrix

这是截断的输出:

matrix = 
[[ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]]
'diag' = 0
[[ 1.  1.  1.  1.  1.  1.  1.  0.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]]
'diag' = 3
[[ 1.  1.  1.  1.  0.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  0.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  0.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  0.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]]
'diag' = 7
[[ 0.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  0.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  0.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  0.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  0.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  0.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  0.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  0.]]
'diag' = 8
[[ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 0.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  0.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  0.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  0.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  0.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  0.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  0.  1.]]
'diag' = 9
[[ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 0.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  0.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  0.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  0.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  0.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  0.  1.  1.]]

答案 3 :(得分:0)

如果我跟着你,这是一个简单的方法:

a       = rand(8,8);
indx    = logical( diag(ones(1,8),0) ); 
a(indx) = 0;

如果您愿意,可以在一行中

a(logical(diag(ones(1,8),0))) = 0;

注意当使用diag(v,k)设置时,k = 1将v放在主对角线上,k = 1将v放在主对角线上方的对角线上,依此类推。

然后通过相应地改变k和v的大小来重复非主对角线。

答案 4 :(得分:0)

另一种方法是直接使用索引。

对于8x8矩阵,如果要将主对角线上或下方的一个对角线中的条目清零,请使用:

M((n+1):9:(64-8*n))=0;

这将沿对角线向下运行,当它到达最低行时停止。对于对角线以上的条目,而不是从n + 1开始,你必须以64-n结束,如下所示:

M((8*n+1):9:(64-n))=0;

在这两种情况下,n都是距主对角线的距离 - 所以n = 0是主对角线。这可以通过一些逻辑推广:

idx=1:9:64;
M(idx((idx+8*n)<65&(idx+8*n)>0)+8*n)=0;

对于n> = 0,这将选择主对角线上方的第n个对角线。负值将选择主对角线下方的对角线。进一步概括,对于NxN矩阵,

idx=1:(N+1):N^2;
M(idx((idx+N*n)<=N^2&(idx+N*n)>0)+N*n)=0;

通过广播或适当使用repmat(或乘以一个矢量),这可以适应一次处理多个对角线,虽然它变得更加混乱。

答案 5 :(得分:0)

假设您有一个方阵M。如果您只想将整个对角线设置为零,那么您可以这样做:

M(sub2ind(size(M), [1:length(M)]',[1:length(M)]')) = 0;

如果你想将一些对角线设置为零,比如说1:5,8:11,你只需修改为:

M(sub2ind(size(M), [1:5, 8:11]',[1:5, 8:11]')) = 0;

其他人建议使用for循环。除非你绝对必须,否则不要在Matlab中使用for循环。原生Matlab功能更快。

答案 6 :(得分:0)

另一种基于Glen O's answer的解决方案也适用于非方形矩阵,如下所示:

%% // Example inputs
N_ROWS = 6;
N_COLS = 4;
A = randi(20,N_ROWS,N_COLS);
DIAG_TO_MODIFY = -1;
REPLACE_VEC = rand(size(diag(A,DIAG_TO_MODIFY))); %// Will error if diagonal # is invalid.

%% // Processing; can be made a function
if  -DIAG_TO_MODIFY > N_ROWS-1 || ... 
     DIAG_TO_MODIFY > N_COLS-1
    error('Invalid diagonal number.');
end

if DIAG_TO_MODIFY < 0
    firstInd = 1 - DIAG_TO_MODIFY;
elseif DIAG_TO_MODIFY > 0
    firstInd = 1 + DIAG_TO_MODIFY*N_ROWS;
else %// DIAG_TO_MODIFY == 0 
    firstInd = 1;
end
A(firstInd:N_ROWS+1:end) = REPLACE_VEC;