如何在MATLAB中随机置换三维矩阵中的列

时间:2011-06-21 19:40:38

标签: matlab matrix random permutation

我有3D矩阵(10000 x 60 x 20),我需要置换第二维和第三维,保持列完好无损。

对于2D矩阵,我使用RANDPERM:

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

我不能只应用RANDPERM两次 - 首先是列索引,然后是页面索引。没有足够的随机化。

一种解决方案是将矩阵从3D压缩到2D以及将页面压缩到列,对其进行置换然后重新整形。但我也想以这样一种方式进行排列,即每列独立地排列列。类似的东西:

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

我可以更有效地完成吗?有更好的方法吗?

3 个答案:

答案 0 :(得分:3)

这是一个可以获得与for循环相同结果的解决方案(即每页​​的列的不同排列):

%# 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);

而且,与MATLAB中的许多问题一样,有许多不同的方法可以解决这个问题。这是另一种解决方案,它通过A只使用linear indexing来避免重新整形矩阵:

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

答案 1 :(得分:3)

解决方案#1:列在所有页面上进行置换

  

将矩阵从3D重塑为2D   挤压列和页面   列,置换它们然后重塑   回

A = randi(10, [3 4 2]);                 %# some random 3D matrix

[r c p] = size(A);
Aperm = reshape(A, [r c*p]);
Aperm = reshape(Aperm(:,randperm(c*p)), [r c p]);

解决方案#2:每个页面中的列独立地(相当于你的for-loop)

  

我也想做排列   这样一种列可以排列   每页独立

A = randi(10, [3 4 2]);                 %# some random 3D matrix

[r c p] = size(A);
Aperm = reshape(A, [r c*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), [r c p]);

答案 2 :(得分:1)

这是一个与你的循环相同的解决方案,但没有像gnovice的答案那样使用kron。虽然我更喜欢kron,但如果你碰巧与那些不了解kron在这里做什么的人(我从经验中说话)分享代码,这是一个更安全的选择。但是,我必须注意,如果pages变大,这会影响性能(在您的情况下,没问题)。

[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{:});