在MATLAB中,我使用shake.m函数(http://www.mathworks.com/matlabcentral/fileexchange/10067-shake)随机地随机播放每一列。例如:
a = [1 2 3; 4 5 6; 7 8 9]
a =
1 2 3
4 5 6
7 8 9
b = shake(a)
b =
7 8 6
1 5 9
4 2 3
此功能完全符合我的要求,但我的列非常长(> 10,000,000),因此需要很长时间才能运行。有谁知道更快的实现方法?我试过分别摇动每个列向量,但这并不快。谢谢!
答案 0 :(得分:8)
您可以像这样使用randperm
,但我不知道它是否会比shake
更快:
[m,n]=size(a)
for c = 1:n
a(randperm(m),c) = a(:,c);
end
或者您可以尝试切换randperm
以查看哪个更快(应该产生相同的结果):
[m,n]=size(a)
for c = 1:n
a(:,c) = a(randperm(m),c);
end
否则你有多少行?如果你的行数远远少于列,那么我们可以假设每个排列都会重复,那么这样的事情怎么样:
[m,n]=size(a)
cols = randperm(n);
k = 5; %//This is a parameter you'll need to tweak...
set_size = floor(n/k);
for set = 1:set_size:n
set_cols = cols(set:(set+set_size-1))
a(:,set_cols) = a(randperm(m), set_cols);
end
会大大减少对randperm
的调用次数。将其分解为k
相等大小的集可能不是最佳的,您可能还想为其添加一些随机性。这里的基本想法是,只有factorial(m)
个不同的排序,如果m
远小于n
(例如m=5
,n=100000
就像你的数据),然后这些排序将自然重复。因此,不要让它自己发生,而是管理流程并减少对randperm
的调用,这无论如何都会产生相同的结果。
答案 1 :(得分:5)
使用randperm获取改组指数
idx = randperm(size(a,1));
使用索引来混洗矢量:
m = size(a,1);
for i=1:m
b(:,i) = a(randperm(m,:);
end
答案 2 :(得分:5)
这是一种简单的矢量化方法。请注意,它会创建一个与ind
大小相同的辅助矩阵(a
),因此根据您的记忆,它可能是否可用。
[~, ind] = sort(rand(size(a))); %// create a random sorting for each column
b = a(bsxfun(@plus, ind, 0:size(a,1):numel(a)-1)); %// convert to linear index
答案 3 :(得分:4)
这是一种无循环的方法,因为它一次处理所有索引,我相信这是随机的,因为只能在每列之间进行混洗。
<强>代码强>
%// Get sizes
[m,n] = size(a);
%// Create an array of randomly placed sequential indices from 1 to numel(a)
rand_idx = randperm(m*n);
%// segregate those indices into rows and cols for the size of input data, a
col = ceil(rand_idx/m);
row = rem(rand_idx,m);
row(row==0)=m;
%// Sort both these row and col indices based on col, such that we have col
%// as 1,1,1,1 ...2,2,2,....3,3,3,3 and so on, which would represent per col
%// indices for the input data. Use these indices to linearly index into a
[scol,ind1] = sort(col);
a(1:m*n) = a((scol-1)*m + row(ind1))
最终输出是在a
本身获得的。