如何改进此代码,以便在MATLAB中从另一个矩阵替换矩阵的元素?
我有4个大小相同的矩阵:如何改进此代码,以便在MATLAB中从另一个矩阵替换矩阵的元素?,matlab,matrix,Matlab,Matrix,我有4个大小相同的矩阵: k = [0.5; 1.0; 1.5; 2.0]; l = [2; 4; 6; 8]; m = [1.7; 3.0; 4.5; 6.0]; n = [2.5; 5.0; 7.5; 10.0]; k = [0.5; 1.0; 1.5; 2.0]; l = [2; 4; 6; 8]; m = [1.7; 3.0; 4.5; 6.0]; n = [2.5; 5.0; 7.5; 10.0]; Y = arrayfun(@(i) [k(i), l(i); m(i), n(i)
k = [0.5; 1.0; 1.5; 2.0];
l = [2; 4; 6; 8];
m = [1.7; 3.0; 4.5; 6.0];
n = [2.5; 5.0; 7.5; 10.0];
k = [0.5; 1.0; 1.5; 2.0];
l = [2; 4; 6; 8];
m = [1.7; 3.0; 4.5; 6.0];
n = [2.5; 5.0; 7.5; 10.0];
Y = arrayfun(@(i) [k(i), l(i); m(i), n(i)], 1:4, 'UniformOutput', false);
blkdiag(Y{:})
X = cat(3, [k, m], [l, n]);
blkdiag(squeeze(X(1,:,:)), squeeze(X(2,:,:)), squeeze(X(3,:,:)), squeeze(X(4,:,:)))
我想把每个矩阵中的元素放到零矩阵的对角线上,这样会产生如下结果:
f = 0.5 2.0 0 0 0 0 0 0
1.7 2.5 0 0 0 0 0 0
0 0 1.0 4.0 0 0 0 0
0 0 3.0 5.0 0 0 0 0
0 0 0 0 1.5 6.0 0 0
0 0 0 0 4.5 7.5 0 0
0 0 0 0 0 0 2.0 8.0
0 0 0 0 0 0 6.0 10.0
这就是我想到的:
f = zeros(8,8);
k = [0.5; 1.0; 1.5; 2.0];
l = [2; 4; 6; 8];
m = [1.7; 3.0; 4.5; 6.0];
n = [2.5; 5.0; 7.5; 10.0];
for i = 1:2:8 %odd index number
for j = 2:2:8 %even index number
f(i,i) = k(1,i)
f(i,j) = l(1,i)
f(j,i) = m(1,i)
f(j,j) = n(i,1)
end;
end;
disp(f)
但是结果将元素不放在矩阵的对角f=0(8,8)
,我总是得到索引的误差超过矩阵维数。
我能得到一些关于如何修复这段代码的建议吗?我想你是打算写这篇文章的:
for i = 2:2:8
f(i-1,i-1) = k(i/2)
f(i-1,i) = l(i/2)
f(i,i-1) = m(i/2)
f(i,i) = n(i/2)
end
虽然必须有更简单的方法来完成同样的事情。例如,查看函数 Cris Luengo的答案比我这里的答案更灵活,读起来也更好,但是如果你要使用MATLAB做大量工作,这可能是你想要学习的东西 (此方法通常性能更好,因为它消除了
for
循环的需要。)
在这里,f
被用作向量(数组),即使它是8*8矩阵。在Matlab中,可以通过指定行数和列数或线性索引从矩阵中访问单个元素
更多的细节可以在这里找到:(参见线性索引)对不起,我错过了“一切都在移动”的主题。我以前的回答完全不正确 我仍然会使用blkdiag,您只需要重新分配矩阵:
k = [0.5; 1.0; 1.5; 2.0];
l = [2; 4; 6; 8];
m = [1.7; 3.0; 4.5; 6.0];
n = [2.5; 5.0; 7.5; 10.0];
k = [0.5; 1.0; 1.5; 2.0];
l = [2; 4; 6; 8];
m = [1.7; 3.0; 4.5; 6.0];
n = [2.5; 5.0; 7.5; 10.0];
Y = arrayfun(@(i) [k(i), l(i); m(i), n(i)], 1:4, 'UniformOutput', false);
blkdiag(Y{:})
X = cat(3, [k, m], [l, n]);
blkdiag(squeeze(X(1,:,:)), squeeze(X(2,:,:)), squeeze(X(3,:,:)), squeeze(X(4,:,:)))
另一种选择是先构造对角线和两个非对角线向量,然后使用
diag
创建矩阵,然后将它们相加
%Data
k = [0.5;1.0;1.5;2.0];
l = [2;4;6;8];
m = [1.7;3.0;4.5;6.0];
n = [2.5;5.0;7.5;10.0];
%Construct vectors
diagonal = [1;0].*k.' + [0;1].*n.'; %Diagonal of the matrix
offu = [1;0].*l'; %Upper diagonal
offl = [1;0].*m'; %Lower diagonal
A = diag(diagonal(:)) + diag(offu(1:end-1),1) + diag(offl(1:end-1),-1);
我不知道它是否比其他答案更快,但我喜欢它对正在发生的事情的透明度
注:为了构造变量
对角线
、offu
和offl
,我使用隐式展开,这需要Matlab R2016b或更新版本。如果您使用的是较旧的版本,您可以使用bsxfun
如果您正在寻找compact,那么下面是一个有趣的解决方案,使用和:
与你的问题无关,尽管我仍然想指出这一点
k
、l
、m
和n
是向量(1D数组)。只需指定一个索引即可访问该值,即k(i)
而不是k(1,i)
。除此之外@anthony还说:k(1,i)
是一个列向量,第一个索引是行号,因此超出了范围。试试k(i,1)
。但这只是学习索引的练习k(i)
更简单、更地道。k((i+1)/2)
其他人也一样:)我想我现在明白了,非常感谢你的帮助!我还将签出blkdiag
函数,使此代码更简单@安东尼:完全正确!我根本没注意写那个,是吗?:)这并没有给出问题中所示的预期结果。。。每个块不是一个向量,而是块中的每个对应元素都来自同一个向量对不起@Wolfie,这是真的。修正了。@Wolfie-true。我之前想更详细地说明这个想法,因此我有idx_k=1:18:nf代码>等。。。后来我决定简化代码,但没有意识到nf
也被重新编译。答案修改了。这个很好!我知道人们会对此给出非常简短的答案不知何故,我希望克朗能成为解决方案的一部分,但我不知道如何…@CrisLuengo:检查我的编辑。起初我用的是kron
,后来改成了repelem
,因为我觉得效率更高。啊,里面有一个kron
!令人惊叹的!在某个时候,我必须学会使用它…:p这一个真的很好,效率很高!谢谢你的建议!