【问题标题】:Shift rows in matrix with respect to vector values in Octave/MATLAB相对于 Octave/MATLAB 中的向量值移动矩阵中的行
【发布时间】:2016-08-20 16:59:10
【问题描述】:

我可以相对于向量v 中的值移动矩阵A 中的行吗?

例如Av指定如下:

A =
    1   0   0
    1   0   0
    1   0   0

v =
    0   1   2

在这种情况下,我想从 A 获取这个矩阵:

A = 
    1   0   0
    0   1   0
    0   0   1

A 中的每个 i-th 行都已移动了 v 中的 i-th 值

我可以使用本机函数执行此操作吗? 还是我自己写?

我试过circshift函数,但我不知道如何单独移动行。

【问题讨论】:

    标签: matlab matrix octave


    【解决方案1】:

    函数circshift 无法按您的意愿工作,即使您使用向量作为移位量,也将其解释为每个维度的移位量。虽然可以循环遍历矩阵的行,但效率不高。

    如果您计算每一行的索引,这实际上非常简单:

    ## First, prepare all your input
    octave> A = randi (9, 4, 6)
    A =
    
       8   3   2   7   4   5
       4   4   7   3   9   1
       1   6   3   9   2   3
       7   4   1   9   5   5
    
    octave> v = [0 2 0 1];
    octave> sz = size (A);
    
    
    ## Compute how much shift per row, the column index (this will not work in Matlab)
    octave> c_idx = mod ((0:(sz(2) -1)) .- v(:), sz(2)) +1
    c_idx =
    
       1   2   3   4   5   6
       5   6   1   2   3   4
       1   2   3   4   5   6
       6   1   2   3   4   5
    
    ## Convert it to linear index    
    octave> idx = sub2ind (sz, repmat ((1:sz(1))(:), 1, sz(2)) , c_idx);
    
    ## All you need is to index
    octave> A = A(idx)
    A =
    
       8   3   2   7   4   5
       9   1   4   4   7   3
       1   6   3   9   2   3
       5   7   4   1   9   5
    

    【讨论】:

    • 我认为matlab刚刚在最新版本中引入了广播。 :)
    • 另外,最好mod 而不是仅仅添加偏移量,因为这是一个公平的假设 v 可能包含负的“转变”
    • @TasosPapastylianou 你对在 Matlab 中广播是认真的吗?请链接。您对mod 的看法是正确的,它会支持负值并且看起来更性感。然后它就和你的答案一样了。
    • 可能是 Julia,但据我所知,Octave 在脚本和命令行中有函数定义。我不认为他们在复制任何其他语言,他们只是在追赶所有其他语言。什么样的现代语言不支持脚本文件中的函数?只有 Matlab 有那么迟钝。
    • 我认为“迟钝”这个词在这里太强了。在其他方面,Octave 落后于 Matlab,我从没想过称它为“迟钝”:-)
    【解决方案2】:
    % A and v as above. These could be function input arguments
    A = [1 0 0; 1 0 0; 1 0 0]; 
    v = [0 1 2];                                          
    assert (all (size (v) == [1, size(A, 1)]), ...
            'v needs to be a horizontal vector with as many elements as rows of A');
    
    % Calculate shifted indices
    [r, c] = size (A);
    tmp = mod (repmat (0 : c-1, r, 1) - repmat (v.', 1, c), c) + 1;
    Out = A(sub2ind ([r, c], repmat ([1 : r].', 1, c), tmp))  
    
      Out =
    
           1     0     0
           0     1     0
           0     0     1
    

    如果性能是一个问题,您可以将repmat 替换为等效的bsxfun 调用,这样更有效(为了简单起见,我在这里使用repmat 来演示该方法)。

    【讨论】:

    • 如果行数和列数不匹配,您对sub2ind 的调用是错误的。以A = randi (9, 3, 6) 为例。
    【解决方案3】:

    关注性能,这是使用bsxfun/broadcasting 的一种方法-

    [m,n] = size(A);
    idx0 = mod(bsxfun(@plus,n-v(:),1:n)-1,n);
    out = A(bsxfun(@plus,(idx0*m),(1:m)'))
    

    示例运行 -

    A =
         1     7     5     7     7
         4     8     5     7     6
         4     2     6     3     2
    v =
         3     1     2
    out =
         5     7     7     1     7
         6     4     8     5     7
         3     2     4     2     6
    

    使用 automatic broadcasting 的等效 Octave 版本看起来像这样 -

    [m,n] = size(A);
    idx0 = mod( ((n-v(:)) + (1:n)) -1 ,n);
    out = A((idx0*m)+(1:m)')
    

    【讨论】:

      【解决方案4】:

      循环中带有circshift 的移位向量,迭代行索引。

      【讨论】:

        猜你喜欢
        • 2013-04-13
        • 1970-01-01
        • 2021-12-04
        • 1970-01-01
        • 2013-08-30
        • 2013-04-18
        • 1970-01-01
        • 1970-01-01
        • 2018-05-16
        相关资源
        最近更新 更多