用另一个矩阵来排序矩阵。

时间:2021-05-14 15:58:35

Suppose I have a matrix A and I sort the rows of this matrix. How do I replicate the same ordering on a matrix B (same size of course)?

假设我有一个矩阵a我把这个矩阵的行排序。如何在矩阵B上复制相同的排序(当然大小相同)?

E.g.

如。

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

This is the best I've come up with

这是我想出的最好的办法。

m = size(A,1);
B = B(bsxfun(@plus,(ind-1)*m,(1:m)'));

Out of curiosity, any alternatives?

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

Update: Jonas' excellent solution profiled on 2008a (XP):

更新: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

n = 2m

0.63202       1.3029       1.1112       1.0501      0.94703      0.92847      0.90411       0.8849       0.8667      0.92098      0.85569

It just goes to show that loops aren't anathema to MATLAB programmers anymore thanks to JITA (perhaps).

它只是表明,由于JITA(也许),对MATLAB编程人员来说,循环不再是一种诅咒。

3 个解决方案

#1


17  

A somewhat clearer way to do this is to use a loop

更清晰的方法是使用循环。

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

Interestingly, the loop version is faster for small (<12 rows) and large (>~700 rows) square arrays (r2010a, OS X). The more columns there are relative to rows, the better the loop performs.

有趣的是,对于小的(<12行)和大的(>~700行)方阵(r2010a, OS X),循环版本更快。

Here's the code I quickly hacked up for testing:

下面是我快速破解的代码:

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,:)

For square arrays

广场的数组

ans =

    0.7149    2.1508    1.2203    1.4684    1.2339    1.1855    1.0212    1.0201    0.8770       0.8584    0.8405

For twice as many columns as there are rows (same number of rows)

因为行数是行数的两倍(相同的行数)

ans =

    0.8431    1.2874    1.3550    1.1311    0.9979    0.9921    0.8263    0.7697    0.6856    0.7004    0.7314

#2


5  

Sort() returns the index along the dimension you sorted on. You can explicitly construct indexes for the other dimensions that cause the rows to remain stable, and then use linear indexing to rearrange the whole array.

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

#3


0  

Can't you just do this?

你就不能这么做吗?

[val ind]=sort(A);
B=B(ind);

It worked for me, unless I'm understanding your problem wrong.

这对我很有效,除非我理解错了你的问题。

#1


17  

A somewhat clearer way to do this is to use a loop

更清晰的方法是使用循环。

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

Interestingly, the loop version is faster for small (<12 rows) and large (>~700 rows) square arrays (r2010a, OS X). The more columns there are relative to rows, the better the loop performs.

有趣的是,对于小的(<12行)和大的(>~700行)方阵(r2010a, OS X),循环版本更快。

Here's the code I quickly hacked up for testing:

下面是我快速破解的代码:

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,:)

For square arrays

广场的数组

ans =

    0.7149    2.1508    1.2203    1.4684    1.2339    1.1855    1.0212    1.0201    0.8770       0.8584    0.8405

For twice as many columns as there are rows (same number of rows)

因为行数是行数的两倍(相同的行数)

ans =

    0.8431    1.2874    1.3550    1.1311    0.9979    0.9921    0.8263    0.7697    0.6856    0.7004    0.7314

#2


5  

Sort() returns the index along the dimension you sorted on. You can explicitly construct indexes for the other dimensions that cause the rows to remain stable, and then use linear indexing to rearrange the whole array.

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

#3


0  

Can't you just do this?

你就不能这么做吗?

[val ind]=sort(A);
B=B(ind);

It worked for me, unless I'm understanding your problem wrong.

这对我很有效,除非我理解错了你的问题。