【问题标题】:Matlab sort every other columnMatlab每隔一列排序
【发布时间】:2015-03-22 21:02:55
【问题描述】:

我的数据看起来像这样重复-

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

非常感谢您的帮助!

【问题讨论】:

    标签: arrays matlab sorting matrix


    【解决方案1】:

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

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

    【讨论】:

    • Hi- 是“M”我上面以未排序形式给出的 5 行 x 4 列数组吗?
    • @user2100039 - 不是我的帖子 :) 是丹尼尔。我正好在附近回答你的问题。
    【解决方案2】:

    矢量化方法

    这假定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));
    

    基准测试

    本部分将提议的矢量化方法与@Daniel's answerlate addition by @Luis 中列出的基于循环的方法进行基准测试。

    基准代码

    %// 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.
    

    【讨论】:

    • 不错的矢量化方法!我已经独立写了另一篇;我希望它不会太相似
    • @LuisMendo 不,我想我也喜欢你的!
    • 感谢您将我加入基准测试。你的代码赢了!我的机器上的结果是相似的(对于稍微小一点的矩阵)
    • @LuisMendo 摆脱了permute,但没有任何巨大的改进。
    【解决方案3】:

    这是另一种矢量化方法。让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
    

    【讨论】:

    • 甜蜜!可能比我的还快!
    • 使用 NaN 有什么特别的原因吗?
    • @Divakar 你的代码在我的机器上要快一点。那些NaNs 仅用于初始化,它们可能是零;或者可以安全地删除该行,因为下一行用作预分配
    • 在我的代码中添加了您的代码计时。你说得对,快一点。
    • 比 Divakar 的解决方案慢一点,但与它相比,这个解决方案将内存开销减少了一半。
    【解决方案4】:

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

    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
    

    将此添加到benchmark,对于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.
    

    【讨论】:

    • 您能否提供一些背景信息来说明您的答案为何解决了这个问题?
    • 这与丹尼尔提供的答案基本相同,但不那么优雅(没有冒犯)。我看不出这比他的回答有什么贡献(已被接受)。
    • 我开始写作的时候不是这样。我真的很想知道这种情况下的礼仪,我应该删除我的答案吗?
    • @yoh.lej - 不,不,你可以离开它。这可能是有人可能会采用的第一原则方法:) 离开它。
    • 不错!可能是因为sortrows 似乎在内部使用sort
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-18
    • 1970-01-01
    相关资源
    最近更新 更多