Shuffle row order within every N rows in a matrix

1 vue (au cours des 30 derniers jours)
Benjy Barnett
Benjy Barnett le 9 Fév 2023
Commenté : Rik le 10 Fév 2023
I would like to shuffle my matrix's rows, but within each miniblock of 8 rows.
So for example, say I have the following 16x5 matrix:
[1 2 4 1 1
1 2 4 2 1
1 2 4 1 2
1 2 4 2 2
1 2 4 1 1
1 2 4 2 1
1 2 4 1 2
1 2 4 2 2
1 2 1 1 1
1 2 1 2 1
1 2 1 1 2
1 2 1 2 2
1 2 1 1 1
1 2 1 2 1
1 2 1 1 2
1 2 1 2 2];
How can I shuffle it so that the first 8 rows are all shuffled with eachother (maintaining column structure), and the second set of 8 rows are shuffled with eachother? Producing something like this:
[1 2 4 1 1
1 2 4 2 2
1 2 4 2 1
1 2 4 1 1
1 2 4 1 2
1 2 4 1 2
1 2 4 2 2
1 2 4 2 1
1 2 1 1 1
1 2 1 1 1
1 2 1 1 2
1 2 1 2 1
1 2 1 2 2
1 2 1 2 1
1 2 1 1 2
1 2 1 2 2];
In reality, my matrix is 384x5, so would be nice to be able to automate this somehow.
  3 commentaires
Luca Ferro
Luca Ferro le 9 Fév 2023
why there is always a plot twist after people start answering lol :)
Benjy Barnett
Benjy Barnett le 10 Fév 2023
All edits were done before people answered :)

Connectez-vous pour commenter.

Réponse acceptée

Voss
Voss le 9 Fév 2023
Here's one way:
I'll use a different matrix that makes it easier to see that the process works:
data = repmat((1:8).'+(0:4),2,1);
disp(data);
1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8 5 6 7 8 9 6 7 8 9 10 7 8 9 10 11 8 9 10 11 12 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8 5 6 7 8 9 6 7 8 9 10 7 8 9 10 11 8 9 10 11 12
n_rows = 8;
N = size(data,1); % N must be a multiple of n_rows for this to work
n_shuffles = N/n_rows;
idx = zeros(n_rows,n_shuffles);
for ii = 1:n_shuffles
idx(:,ii) = randperm(n_rows);
end
new_data = data(idx(:),:);
disp(new_data);
3 4 5 6 7 5 6 7 8 9 2 3 4 5 6 6 7 8 9 10 4 5 6 7 8 8 9 10 11 12 1 2 3 4 5 7 8 9 10 11 3 4 5 6 7 5 6 7 8 9 8 9 10 11 12 7 8 9 10 11 1 2 3 4 5 4 5 6 7 8 2 3 4 5 6 6 7 8 9 10
  1 commentaire
Rik
Rik le 10 Fév 2023
If your matrix is not a multiple of n_rows, you need edits like in my answer.

Connectez-vous pour commenter.

Plus de réponses (2)

Luca Ferro
Luca Ferro le 9 Fév 2023
Modifié(e) : Luca Ferro le 9 Fév 2023
i think this would do the trick:
[rows,~]=size(m);
if mod(rows,2)==0 %detects if even or odd number of rows
half=rows/2;
topHalf=m(1:half,:) %split matrix in half
bottomHalf=m(1+half :end,:)
else
half=(rows+1)/2; %the middle row will be left unshuffled
topHalf=m(1:half-1,:) %split matrix in half
bottomHalf=m(1+half :end,:)
end
topShuffle=randperm(half);
bottomShuffle=randperm(half);
m=[topHalf(topShuffle,:);bottomHalf(bottomShuffle,:)] %merges halves to recreate full

Rik
Rik le 9 Fév 2023
Just use a loop with randperm:
data=[
1 2 4 1 1
1 2 4 2 1
1 2 4 1 2
1 2 4 2 2
1 2 4 1 1
1 2 4 2 1
1 2 4 1 2
1 2 4 2 2
1 2 1 1 1
1 2 1 2 1
1 2 1 1 2
1 2 1 2 2
1 2 1 1 1
1 2 1 2 1
1 2 1 1 2
1 2 1 2 2];
k=4; % You want 8, but that is a big example
rng(0) % make the result the same each run for this example
sz = size(data,1);
for base_row=1:k:sz
base_row
block_indices = randperm( min(sz-base_row,k) );
ind1 = base_row + (1:numel(block_indices))
ind2 = base_row + block_indices
data(ind2,:) = data(ind1,:);
end
base_row = 1
ind1 = 1×4
2 3 4 5
ind2 = 1×4
4 2 3 5
base_row = 5
ind1 = 1×4
6 7 8 9
ind2 = 1×4
7 8 9 6
base_row = 9
ind1 = 1×4
10 11 12 13
ind2 = 1×4
12 10 11 13
base_row = 13
ind1 = 1×3
14 15 16
ind2 = 1×3
15 16 14

Catégories

En savoir plus sur Resizing and Reshaping Matrices dans Help Center et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by