在MATLAB中对矩阵中每列的非零元素进行混洗

时间:2018-04-13 21:24:58

标签: matlab random

我想要在矩阵中混洗每列的非零元素,但是将零元素保持在同一个位置。就像我有这个:

A = 
 [10    0     30    40    50    60
  11    0     31    41    0     61
  0     22    32    42    0     62
  13    23    0     43    0     63
  0     24    34    44    54    64
  15    0     35    0     0     65
  16    26    36    46    56    66]

我想要这个:

B =
   [13    0     32    44    54    64
    11    0     35    42    0     63
    0     24    36    40    0     61
    16    23    0     43    0     62
    0     22    31    41    56    60
    10    0     30    0     0     66
    15    26    34    46    50    65]

因此,我在完全相同的位置(即~A = ~B)处有零,并且非零元素被混洗。显然使用&raffperm'拖曳柱子。不起作用,因为它不允许我在同一个地方保留零!

3 个答案:

答案 0 :(得分:3)

这是显式循环列方法的替代方法:

[~, jj, vv] = find(A);
s = accumarray(jj, vv, [], @(x){x(randperm(numel(x)))});
B = A;
B(B~=0) = cell2mat(s);

答案 1 :(得分:2)

这是一个适用于一列的解决方案:创建一个包含非零条目的新向量C,对它们进行混洗,然后将它们粘贴回B的非零条目中应该完全相同。现在,您可以通过循环遍历所有列来调整此值以适用于矩阵。

A =  [10, 11, 0, 13, 0, 15, 16];
B = A;
C = A(A~=0);
B(A~=0) = C(randperm(numel(C)));
A
B

Try it online!

答案 2 :(得分:1)

我为你写了一个函数

function a=shuffle(src) 

[rows, cols] = size(src);
a = zeros(rows,cols);

for c = 1:cols
    lastIndex = 1;
    col = [];
    for r = 1:rows
        if(src(r,c) ~= 0)
            col(lastIndex) = src(r,c);
            lastIndex = lastIndex + 1;
        end
    end

    indexes = randperm(length(col));
    lastIndex = 1;

    for r = 1:rows
        if(src(r,c) == 0)
            a(r,c) = 0;
        else
            a(r,c) = col(indexes(lastIndex));
            lastIndex = lastIndex + 1;
        end
    end
end
end

它没有优化,我留给你。 它将非零提取到一个向量,并将该向量中的randperm值带到新矩阵,如果旧矩阵在那里没有0。