用另一个矩阵对矩阵进行排序

Jac*_*cob 21 matlab bsxfun

假设我有一个矩阵A,我对这个矩阵的行进行排序.如何在矩阵上复制相同的顺序B(当然大小相同)?

例如

A = rand(3,4);
[val ind] = sort(A,2);
B = rand(3,4);
%// Reorder the elements of B according to the reordering of A
Run Code Online (Sandbox Code Playgroud)

这是我提出的最好的

m = size(A,1);
B = B(bsxfun(@plus,(ind-1)*m,(1:m)'));
Run Code Online (Sandbox Code Playgroud)

出于好奇,还有其他选择吗?

更新: Jonas在2008a(XP)上的优秀解决方案:

n = n

0.048524       1.4632       1.4791        1.195       1.0662        1.108       1.0082      0.96335      0.93155      0.90532      0.88976
Run Code Online (Sandbox Code Playgroud)

n = 2米

0.63202       1.3029       1.1112       1.0501      0.94703      0.92847      0.90411       0.8849       0.8667      0.92098      0.85569
Run Code Online (Sandbox Code Playgroud)

它只是表明,由于JITA(或许),循环不再是MATLAB程序员的诅咒.

Jon*_*nas 17

更简单的方法是使用循环

A = rand(3,4);
B = rand(3,4);
[sortedA,ind] = sort(A,2);

for r = 1:size(A,1)
   B(r,:) = B(r,ind(r,:));
end
Run Code Online (Sandbox Code Playgroud)

有趣的是,对于小型(<12行)和大型(> ~700行)方阵(r2010a,OS X),循环版本更快.相对于行的列越多,循环执行得越好.

这是我快速入侵测试的代码:

siz = 10:100:1010;
tt = zeros(100,2,length(siz));

for s = siz
    for k = 1:100

        A = rand(s,1*s);
        B = rand(s,1*s);
        [sortedA,ind] = sort(A,2);

        tic;
        for r = 1:size(A,1)
            B(r,:) = B(r,ind(r,:));
        end,tt(k,1,s==siz) = toc;

        tic;
        m = size(A,1);
        B = B(bsxfun(@plus,(ind-1)*m,(1:m).'));
        tt(k,2,s==siz) = toc;

    end
end

m = squeeze(mean(tt,1));

m(1,:)./m(2,:)
Run Code Online (Sandbox Code Playgroud)

对于方阵

ans =

    0.7149    2.1508    1.2203    1.4684    1.2339    1.1855    1.0212    1.0201    0.8770       0.8584    0.8405
Run Code Online (Sandbox Code Playgroud)

列数是行的两倍(行数相同)

ans =

    0.8431    1.2874    1.3550    1.1311    0.9979    0.9921    0.8263    0.7697    0.6856    0.7004    0.7314
Run Code Online (Sandbox Code Playgroud)


And*_*nke 5

Sort()返回您排序的维度的索引.您可以显式构造导致行保持稳定的其他维度的索引,然后使用线性索引重新排列整个数组.

A = rand(3,4);
B = A; %// Start with same values so we can programmatically check result

[A2 ix2] = sort(A,2);
%// ix2 is the index along dimension 2, and we want dimension 1 to remain unchanged
ix1 = repmat([1:size(A,1)]', [1 size(A,2)]); %//'
%// Convert to linear index equivalent of the reordering of the sort() call
ix = sub2ind(size(A), ix1, ix2) 
%// And apply it
B2 = B(ix)
ok = isequal(A2, B2) %// confirm reordering
Run Code Online (Sandbox Code Playgroud)

  • @Jacob:`repmat`只有一个函数.当我这样阅读`repmat`时,我知道会发生什么.当我读"bsxfun"时,我知道我现在必须要注意了.话虽如此,每次我写"bsxfun"时都会让我开心.bsxfun bsxfun bsxfun (2认同)