【问题标题】:How to improve this code for replacing elements of a matrix from another matrices in MATLAB?如何改进此代码以从 MATLAB 中的另一个矩阵中替换矩阵的元素?
【发布时间】:2018-07-17 01:53:58
【问题描述】:

所以我有这 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];

我想将每个矩阵中的元素放入零矩阵的对角线,所以它会创建这样的东西:

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=zero(8,8)的对角线上,一直报Index exceeds matrix dimensions.的错误

我能得到一些关于如何修复此代码的指示吗?

【问题讨论】:

  • 与您的问题无关,但我仍然想指出这一点。 k、l、m 和 n 是向量(一维数组)。您只需指定一个索引即可访问该值,即k(i) 而不是k(1,i)。
  • 除了@anthony 所说的:k(1,i) 超出范围,因为它是列向量,第一个索引是行号。请改用k(i,1)。但这只是作为学习索引的练习。 k(i) 更简单、更惯用。

标签: matlab matrix


【解决方案1】:

我想你打算写这个:

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

虽然必须有更简单的方法来完成同样的事情。例如查看函数blkdiag!

【讨论】:

  • k((i+1)/2) 和其他人一样:)
  • 我想我现在明白了,非常感谢您的帮助!我也会检查blkdiag 函数,以使这段代码更简单!
  • @Anthony:完全正确!我根本没有注意写那个,是吗? :)
【解决方案2】:

如果您正在寻找紧凑型,那么这里有一个有趣的解决方案,使用 eye、repelem 和 logical indexing:

>> f = zeros(8);
>> f(repelem(eye(4, 'logical'), 2, 2)) = [k m l n].';

f =

    0.5000    2.0000         0         0         0         0         0         0
    1.7000    2.5000         0         0         0         0         0         0
         0         0    1.0000    4.0000         0         0         0         0
         0         0    3.0000    5.0000         0         0         0         0
         0         0         0         0    1.5000    6.0000         0         0
         0         0         0         0    4.5000    7.5000         0         0
         0         0         0         0         0         0    2.0000    8.0000
         0         0         0         0         0         0    6.0000   10.0000

【讨论】:

  • 这个不错!我知道人们会对此提出非常简短的答案。 :) 不知何故,我希望 kron 能成为解决方案的一部分,但我不明白如何......
  • @CrisLuengo:检查我的编辑。我一开始用kron,后来改成repelem,因为我觉得效率更高。
  • 啊,里面有一个kron!惊人的!我将不得不在某个时候学会使用它......:p
  • 这个真的很好用,效率很高!感谢您的建议!
【解决方案3】:

Cris Luengo 的答案比我在这里的答案更灵活,读起来也更好,但如果你会使用 MATLAB 做很多工作,这可能是你想要学习的东西。

(此方法通常性能更好,因为它不需要for 循环。)

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];

f = zeros(8); % to create a square matrix, you only need to specify the size with one value

f(1:18:end) = k;
f(9:18:end) = l;
f(2:18:end) = m;
f(10:18:end) = n;

这里,f 被用作一个向量(数组),即使它是一个 8*8 矩阵。在 Matlab 中,您可以通过指定行号和列号或线性索引来访问矩阵中的单个元素。

更多细节可以在这里找到:https://uk.mathworks.com/help/matlab/math/matrix-indexing.html(见线性索引)

【讨论】:

  • @Wolfie 是的。我以前想更详细地展示这个想法,因此有idx_k = 1:18:nf; 等......后来我决定简化代码,并没有意识到nf 也被冗余了。答案已修改。
【解决方案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);    

我不知道它是否比其他答案更快,但我喜欢它对正在发生的事情的透明性。

注意:为了构造变量 diagonal、offu 和 offl,我使用了需要 Matlab R2016b 或更高版本的隐式扩展。如果您使用的是旧版本,则可以改用bsxfun。

【讨论】:

    【解决方案5】:

    对不起,我错过了一切都转移了。我之前的回答完全不正确……

    我仍然会使用 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];
    
    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,:,:)))
    

    【讨论】:

    • 这并没有给出问题中所示的预期结果...每个块不是一个向量,而是一个块中的每个对应元素都来自同一个向量
    • 对不起@Wolfie,这是真的。固定。
    猜你喜欢
    • 1970-01-01
    • 2013-03-14
    • 1970-01-01
    • 2017-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-11
    • 1970-01-01
    相关资源
    最近更新 更多