我可以相对于向量v
中的值移动矩阵A
中的行吗?
例如,指定如下的A
和v
:
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
的移位向量,迭代行索引。