45

假设我有一个 NxN 矩阵 A、一个由数字 1:N 的子集组成的索引向量 V 和一个值 K,我想这样做:

 for i = V
     A(i,i) = K
 end

有没有办法在一个带有矢量化的语句中做到这一点?

例如 A(某物)= K

该语句A(V,V) = K不起作用,它分配了非对角元素,这不是我想要的。例如:

>> A = zeros(5);
>> V = [1 3 4];
>> A(V,V) = 1

A =

 1     0     1     1     0
 0     0     0     0     0
 1     0     1     1     0
 1     0     1     1     0
 0     0     0     0     0
4

7 回答 7

62

我通常为此使用EYE

A = magic(4)
A(logical(eye(size(A)))) = 99

A =
    99     2     3    13
     5    99    10     8
     9     7    99    12
     4    14    15    99

或者,您可以只创建线性索引列表,因为从一个对角线元素到下一个,它需要nRows+1以下步骤:

[nRows,nCols] = size(A);
A(1:(nRows+1):nRows*nCols) = 101
A =
   101     2     3    13
     5   101    10     8
     9     7   101    12
     4    14    15   101

如果您只想访问对角元素的子集,则需要创建对角索引列表:

subsetIdx = [1 3];
diagonalIdx = (subsetIdx-1) * (nRows + 1) + 1;
A(diagonalIdx) = 203
A =
   203     2     3    13
     5   101    10     8
     9     7   203    12
     4    14    15   101

或者,您可以使用创建逻辑索引数组diag(仅适用于方形数组)

diagonalIdx = false(nRows,1);
diagonalIdx(subsetIdx) = true;
A(diag(diagonalIdx)) = -1
A =
    -1     2     3    13
     5   101    10     8
     9     7    -1    12
     4    14    15   101
于 2010-10-18T21:32:40.680 回答
24
>> tt = zeros(5,5)
tt =
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
>> tt(1:6:end) = 3
tt =
     3     0     0     0     0
     0     3     0     0     0
     0     0     3     0     0
     0     0     0     3     0
     0     0     0     0     3

更一般的:

>> V=[1 2 5]; N=5;
>> tt = zeros(N,N);
>> tt((N+1)*(V-1)+1) = 3
tt =
     3     0     0     0     0
     0     3     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     3

这是基于矩阵可以作为一维数组(向量)访问的事实,其中 2 个索引 (m,n) 被线性映射 m*N+n 替换。

于 2010-10-18T21:33:21.363 回答
3
>> B=[0,4,4;4,0,4;4,4,0]

B =

     0     4     4
     4     0     4
     4     4     0

>> v=[1,2,3]

v =

     1     2     3

>> B(eye(size(B))==1)=v
%insert values from v to eye positions in B

B =

     1     4     4
     4     2     4
     4     4     3
于 2018-05-25T00:51:20.060 回答
2
A = zeros(7,6);
V = [1 3 5];

[n m] = size(A);
diagIdx = 1:n+1:n*m;
A( diagIdx(V) ) = 1

A =
     1     0     0     0     0     0
     0     0     0     0     0     0
     0     0     1     0     0     0
     0     0     0     0     0     0
     0     0     0     0     1     0
     0     0     0     0     0     0
     0     0     0     0     0     0
于 2010-10-18T21:39:10.337 回答
2

假设 K 是值。命令

A=A-diag(K-diag(A))

可能会快一点

>> A=randn(10000,10000);

>> tic;A(logical(eye(size(A))))=12;toc

经过的时间是 0.517575 秒。

>> tic;A=A+diag((99-diag(A)));toc

经过的时间是 0.353408 秒。

但它会消耗更多的内存。

于 2011-03-26T02:57:23.623 回答
2

我将使用sub2ind和传递对角线索引作为 x 和 y 参数:

A = zeros(4)
V=[2 4]

idx = sub2ind(size(A), V,V)
% idx = [6, 16]

A(idx) = 1

% A =
% 0     0     0     0
% 0     1     0     0
% 0     0     0     0
% 0     0     0     1
于 2014-02-20T21:51:15.167 回答
1

我在有限差分代码中使用这个小的内联函数。

A=zeros(6,3);
range=@(A,i)[1-min(i,0):size(A,1)-max(i+size(A,1)-size(A,2),0 ) ];
Diag=@(A,i) sub2ind(size(A), range(A,i),range(A,i)+i );
A(Diag(A, 0))= 10; %set diagonal 
A(Diag(A, 1))= 20; %equivelent to diag(A,1)=20;
A(Diag(A,-1))=-20; %equivelent to diag(A,-1)=-20;

通过更改函数范围,可以轻松修改它以在对角线的子范围上工作。

于 2020-11-04T23:32:12.043 回答