我有 8x8 矩阵,其中有 15 条对角线。左上角“对角线 1”和右下角“对角线 15”。我想将特定的对角线集归零,例如 {9, 10, 11, 12, 13, 14, 15} 或 {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} . 有人请给我解决方案吗?
7 回答
我相信你可以使用:
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
另一种方法是直接使用索引。
对于 8x8 矩阵,如果要将主对角线处或下方的对角线之一中的条目归零,请使用以下命令:
M((n+1):9:(64-8*n))=0;
这将沿着对角线运行,当它到达最低行时停止。对于对角线以上的条目,您必须在 64-n 处结束,而不是从 n+1 开始,如下所示:
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(或乘以一个向量),这可以适应一次处理多个对角线,尽管它变得更加混乱。
我不确定我是否正确理解了您的问题。您是想将主对角线上的某些元素子集归零,还是试图将整个对角线归零?无论哪种方式,您都可以考虑使用 Matlab 的“诊断”功能。
如果你只想将主对角线上的一些元素归零,你可以使用类似的东西:
% 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 个对角线归零实际上更容易:
假设你想将第三条对角线归零,你会这样做: A = A - diag(diag(A,3),3);
假设您有一个方阵 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 函数要快得多。
如果我跟着你,这里有一个简单的方法:
a = rand(8,8);
indx = logical( diag(ones(1,8),0) );
a(indx) = 0;
或者如果您愿意,可以在 1 行中,
a(logical(diag(ones(1,8),0))) = 0;
请注意,当使用 diag(v,k) 设置 k=1 时,将 v 放置在主对角线上,k=1 将 v 放置在对角线上,主对角线上方一个位置,依此类推。
然后通过相应地改变 k 和 v 的大小来重复非主对角线。
我认为我的对角线是相反的,但你应该明白这一点。
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.]]
另一种基于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;