Векторизация в случайном порядке для блоков строк матрицы - PullRequest
4 голосов
/ 02 июля 2019

У меня есть простая 5x15 матрица, называемая mat_orig. Я хотел бы разделить эту матрицу на неперекрывающиеся блоки, причем каждый блок имеет длину 3. Это эквивалентно размещению трех непересекающихся строк в одном блоке (то есть имеется 5 блоков размером 3x5).

Затем я бы хотел перемешать mat_orig и сгенерировать новую матрицу. Я использую randi, чтобы случайным образом нарисовать пять блоков.

Мне удалось выполнить задачу, используя код ниже. Тем не менее, мне интересно, смогу ли я избавиться от цикла for? Можно ли применить векторизацию?

mat_orig = reshape(1:75, 5, 15)';

block_length = 3;

num_blocks = size(mat_orig, 1) / block_length;

rand_blocks = randi(num_blocks, num_blocks, 1);

mat_shuffled = nan(size(mat_orig));

for r = 0 : num_blocks - 1
    start_row_orig = r * block_length + 1;
        end_row_orig = r * block_length + block_length;
    start_row_random_blocks = ...
        rand_blocks(r + 1) * block_length - block_length + 1;
    end_row_random_blocks = ...
        rand_blocks(r + 1) * block_length;

    mat_shuffled(start_row_orig:end_row_orig, :) = ...
        mat_orig(start_row_random_blocks:end_row_random_blocks, :);
end

1 Ответ

3 голосов
/ 02 июля 2019

Вы можете сделать это с неявным расширением для создания индексов блоков, подробности см. В комментариях к коду.

mat_orig = reshape(1:75, 5, 15)';
block_length = 3;
num_blocks = size(mat_orig,1) / block_length;

% Get the shuffle order (can repeat blocks)
shuffIdx = randi( num_blocks, num_blocks, 1 ).';
% Expand these indices to fill the blocks
% This uses implicit expansion to create a matrix, and 
% will only work in R2016b or newer.
% For older versions, use 'bsxfun'
shuffIdx = block_length * shuffIdx - (block_length-1:-1:0).';
% Create the shuffled output
mat_shuffled = mat_orig( shuffIdx(:), : );
...