如何在没有循环的情况下执行矩阵的列循环移位

时间:2012-07-20 18:07:49

标签: matlab

我需要循环移动矩阵的各个列。

如果你想将所有列移动相同的数量,这很容易,但是,在我的情况下,我需要将它们全部移动不同的数量。

目前我正在使用循环,如果可能的话,我想删除循环并使用更快的,基于矢量的方法。

我当前的代码

A = randi(2, 4, 2);
B = A;
for i = 1:size( A,2 );
   d = randi( size( A,1 ));
   B(:,i) = circshift( A(:,i), [d, 0] );
end

是否可以从此代码中删除循环?

更新我测试了所有三种方法,并将它们与此问题中描述的循环进行了比较。我计算了在1000x1000矩阵上按列循环移位100次执行列所需的时间。我重复了几次这个测试。

结果

  • 我的循环花了超过12秒
  • Pursuit的建议不到一秒
  • Zroth的原始答案仅用了2秒钟
  • Ansari的建议比原始循环慢

3 个答案:

答案 0 :(得分:3)

修改

追求是对的:使用for循环和适当的索引似乎是这里的方式。这是一种方法:

[m, n] = size(A);
D = randi([0, m - 1], [1, n]);
B = zeros(m, n);

for i = (1 : n)
    B(:, i) = [A((m - D(i) + 1 : m), i); A((1 : m - D(i) ), i)];
end

原始答案

之前我曾经找过类似的东西,但我从未遇到过一个好的解决方案。使用here之一的算法的修改在我的测试中略微提升了性能:

[m, n] = size(A);
mtxLinearIndices ...
    = bsxfun(@plus, ...
             mod(bsxfun(@minus, (0 : m - 1)', D), m), ...
             (1 : m : m * n));
C = A(idxs);

丑?当然。就像我说的那样,它似乎稍快一些(对我来说要快2-3倍);但是这两种算法的时间都在m = 3000n = 1000不到一秒钟(在一台相当旧的计算机上)。

值得注意的是,对我来说,这两种算法似乎都优于Ansari提供的算法,尽管他的回答肯定更直接。 (Ansari的算法输出与我的其他两种算法不一致;但这可能只是变换应用方式的差异。)一般来说,arrayfun似乎很慢,当我尝试使用它时。细胞阵列对我来说似乎也很慢。但我的测试可能会有某种偏见。

答案 1 :(得分:0)

不确定这会有多快,但你可以试试这个:

[nr, nc] = size(A);
B = arrayfun(@(i) circshift(A(:, i), randi(nr)), 1:nc, 'UniformOutput', false);
B = cell2mat(B);

你必须对它进行基准测试,但使用arrayfun可能会加快它的速度。

答案 2 :(得分:-1)

我怀疑,你的循环移位,对随机整数矩阵的操作不再使它更随机,因为数字是均匀分布的。

所以我希望你的问题是使用randi()仅用于演示目的。