Matlab 每隔一列排序

Matlab sort every other column

我有这样的重复模式数据-

years cf1  years  cf2
2010   45  2010   37
2011   39  2011   29
2012   51  2012   31
2013   25  2013   33 
2014   35  2014   28

我需要数据或数组在按 "cfX" 变量排序后每隔一列看起来像这样。

years cf1  years cf2
2013  25   2014  28
2014  35   2011  29
2011  39   2012  31
2010  45   2013  33
2012  51   2010  37

非常感谢您的帮助!

对于每组两列,您可以使用 sortrows

for idx=1:2:size(M,2)
    M(:,idx:idx+1)=sortrows(M(:,idx:idx+1),2)
end

另一种基于循环的方法,仅使用排序:

disp('----------------------------------------  With other loop based approach')
tic
Aout3 = zeros(size(A));
for i=0:size(A,2)/2-1
  [ord iord]=sort(A(:,2*i+2),'ascend');
  Aout3(:,2*i+1)=A(iord,2*i+1);
  Aout3(:,2*i+2)=ord;
end
toc

将此添加到 ,对于 A=rand(5000) 我得到:

----------------------------------------  With vectorized approach
Elapsed time is 1.415872 seconds.
----------------------------------------  With loop based approach
Elapsed time is 1.997568 seconds.
----------------------------------------  With Luis Vectorized approach
Elapsed time is 1.560120 seconds.
----------------------------------------  With other loop based approach
Elapsed time is 1.566022 seconds.

矢量化方法

这假设 A 是输入矩阵。

[m,n] = size(A);  %// size of input matrix
[~,id] = sort(A(:,2:2:end),1); %// sorted IDs

%// Use id to get linear indices of all elements based on asked sorting criteria
%// and index into A for the final output
Aout = A(bsxfun(@plus,reshape(repmat(permute(id,[1 3 2]),1,2),m,n),[0:n-1]*m));

最后一行可以替换为以下代码,这似乎为小数据量提供了边际运行时改进 -

Aout = A(bsxfun(@plus,reshape(repmat(id,2,1),m,n),[0:n-1]*m));

基准测试

本节将提出的矢量化方法与 and 中列出的基于循环的方法进行基准测试。

基准代码

%// Random huge input array
A = rand(10000);

disp('----------------------------------------  With vectorized approach')
tic
[m,n] = size(A);  %// size of input matrix
[~,id] = sort(A(:,2:2:end),1); %// sorted IDs

%// Use id to get linear indices of all elements based on asked sorting criteria 
Aout = A(bsxfun(@plus,reshape(repmat(permute(id,[1 3 2]),1,2),m,n),[0:n-1]*m));
toc
clear Aout m n id

disp('----------------------------------------  With loop based approach')
tic
Aout2 = zeros(size(A));
for idx=1:2:size(A,2)
    Aout2(:,idx:idx+1)=sortrows(A(:,idx:idx+1),2);
end
toc
clear Aout2 idx

disp('----------------------------------------  With Luis Vectorized approach')
tic
[m, n] = size(A);
[~, rows] = sort(A(:,2:2:n)); %// indices to sort columns 2, 4,...
ind = bsxfun(@plus, rows, (0:n/2-1)*2*m); %// convert to linear index
y = NaN(m,n);
y(:,2:2:n) = A(ind+m); %// fill columns 2, 4,... sorted
y(:,1:2:n) = A(ind);  %// fill columns 1, 3,... with the same order
toc

运行时间

----------------------------------------  With vectorized approach
Elapsed time is 2.244272 seconds.
----------------------------------------  With loop based approach
Elapsed time is 3.255867 seconds.
----------------------------------------  With Luis Vectorized approach
Elapsed time is 2.800249 seconds.

这是另一种矢量化方法。让 x 表示您的矩阵。

[m, n] = size(x);
[~, rows] = sort(x(:,2:2:n)); %// indices to sort columns 2, 4,...
ind = bsxfun(@plus, rows, (0:n/2-1)*2*m); %// convert to linear index
y = NaN(m,n); %// you can remove this line if `y` is assured not to exist,
              %// because in that case the next line serves as preallocation
y(:,2:2:n) = x(ind+m); %// fill columns 2, 4,... sorted
y(:,1:2:n) = x(ind);  %// fill columns 1, 3,... with the same order