相对于Octave/MATLAB中的矢量值移动矩阵中的行



我可以相对于向量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行都被v 中的第i值移位

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

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

函数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
% 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

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

关注性能,这里有一种使用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的等效倍频程版本看起来像这样-

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

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

最新更新