简体   繁体   中英

Shuffling non-zero elements of each column in a matrix in MATLAB

I want to shuffle non-zero elements of each column in a matrix but keep the zero elements at the same place. Like I have this:

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]

And I want this:

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]

So herein I have the zeros at the exact same place (ie ~A = ~B) and the non-zero elements are shuffled. Obviously shuffling the columns using 'randperm' does not work as it does not allow me to keep zeroes at the same place!

Here's an alternative to the explicit loop-over-columns approach:

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

This is a solution that works for one column: Making a new vector C containing the nonzero entries, shuffling those, and pasting them back into the nonzero entries of B should do exactly that. Now you can adjust this to work for matrices by looping over all columns.

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!

I wrote a function for you

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

It's not optimized, I leave it to You. It extracts the non-zeros to a vector, and takes randperm values from this vector to the new matrix, if the old matrix didnt have 0 there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM