How to randomly rearrange columns in a 3D matrix in MATLAB

I have a 3D matrix (10000 x 60 x 20), and I need to rearrange the 2nd and 3rd dimensions, keeping the columns intact.

For a 2D matrix, I use RANDPERM:

pidx = randperm(size(A,2)); Aperm = A(:,pidx); 

I can't just apply RANDPERM twice - first the column index, then the page index. Not enough randomization.

One solution is to change the matrix from 3D to 2D by squeezing columns and pages to columns, rearranging them, and then rearranging them. But I would also like to rearrange so that the columns are rearranged independently for each page. Sort of:

 Aperm = zeros(size(A)); for p=1:size(A,3) pidx = randperm(size(A,2)); Aperm(:,:,p) = A(:,pidx,p); end 

Can I do it more efficiently? Any better ways?

+6
source share
3 answers

Solution # 1: Columns Rebuild on All Pages

change the matrix from 3D to 2D squeeze columns and page columns, rearrange them, and then change back

 A = randi(10, [3 4 2]); %# some random 3D matrix [rcp] = size(A); Aperm = reshape(A, [rc*p]); Aperm = reshape(Aperm(:,randperm(c*p)), [rcp]); 

Solution # 2: Columns are rebuilt on each page independently (which is equivalent to your loop)

I would also like to rearrange in such a way that the columns are rearranged independently for each page

 A = randi(10, [3 4 2]); %# some random 3D matrix [rcp] = size(A); Aperm = reshape(A, [rc*p]); [~,idx] = sort(rand(p,c),2); %# this is what RANDPERM does idx = reshape(bsxfun(@plus, idx',0:c:c*(p-1)),1,[]); %'# Aperm = reshape(Aperm(:,idx), [rcp]); 
+3
source

Here is one solution that will achieve the same result as your for loop (i.e. another column permutation for each page):

 %# Solution 1: [r,c,p] = size(A); Aperm = reshape(A,r,c*p); index = arrayfun(@randperm,c.*ones(1,p),'UniformOutput',false); index = [index{:}]+kron(0:c:c*(p-1),ones(1,c)); Aperm = reshape(Aperm(:,index),r,c,p); 

And, as with many problems in MATLAB, there are many ways to solve this problem. Here's another solution that avoids changing the matrix using linear indexing in A :

 %# Solution 2: [r,c,p] = size(A); Aperm = zeros([rcp]); index1 = repmat(1:r,1,c*p); [~,index2] = sort(rand(c,p)); %# A variation on part of Amro answer index2 = kron(index2(:),ones(r,1)).'; %' index3 = kron(1:p,ones(1,r*c)); index = sub2ind([rcp],index1,index2,index3); Aperm(:) = A(index); 
+3
source

Here is a solution that matches your loop, but without using kron , as in gnovice. Although I prefer kron , it is a safer alternative if you are going to share the code with people who don’t understand what kron is doing kron (I am speaking from experience). However, I should note that this will affect performance if pages get large (in your case, this is normal).

 [rows,cols,pages]=size(A); randCols=arrayfun(@(x)randperm(cols),1:pages,'UniformOutput',false); Aperm=arrayfun(@(x)A(:,randCols{x},x),1:pages,'UniformOutput',false); Aperm=cat(3,Aperm{:}); 
+1
source

Source: https://habr.com/ru/post/891050/


All Articles