Shuffle row order within every N rows in a matrix

4 ビュー (過去 30 日間)
Benjy Barnett
Benjy Barnett 2023 年 2 月 9 日
コメント済み: Rik 2023 年 2 月 10 日
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 件のコメント
Luca Ferro
Luca Ferro 2023 年 2 月 9 日
why there is always a plot twist after people start answering lol :)
Benjy Barnett
Benjy Barnett 2023 年 2 月 10 日
All edits were done before people answered :)

サインインしてコメントする。

採用された回答

Voss
Voss 2023 年 2 月 9 日
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 件のコメント
Rik
Rik 2023 年 2 月 10 日
If your matrix is not a multiple of n_rows, you need edits like in my answer.

サインインしてコメントする。

その他の回答 (2 件)

Luca Ferro
Luca Ferro 2023 年 2 月 9 日
編集済み: Luca Ferro 2023 年 2 月 9 日
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 2023 年 2 月 9 日
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

カテゴリ

Help Center および File ExchangeResizing and Reshaping Matrices についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by