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
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.