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