【问题标题】:How to sort the columns of a matrix in order of some other vector in MATLAB?如何在MATLAB中按其他向量的顺序对矩阵的列进行排序?
【发布时间】:2016-12-07 17:38:13
【问题描述】:

假设我有一个包含项目 ID 的向量 A

A=[50936
   332680
   107430
   167940
   185820
   99732
   198490
   201250
   27626
   69375];

我有一个矩阵 B,它的行包含向量 A 中每个项目的 8 个参数的值:

B=[0    0   0   0   0   0   0   0   0   0
   0    0   0   0   0   0   0   0   0   0
   1    0   1   0   0   1   0   1   1   1
   1    0   1   0   0   1   0   1   1   1
   0    0   1   0   0   0   0   1   0   1
   0    0   0   0   0   0   0   1   0   0
   0    0   0   0   0   0   0   0   0   0
   0    0   0   0   0   0   0   0   0   1];

所以,矩阵B的第1列代表向量A第1行的item数据,矩阵B的第2列代表向量A第2行的item数据,以此类推。但是,我希望矩阵 B 包含以不同顺序存储在向量 A2 中的项目的信息:

A2=[185820
    198490
    69375
    167940
    99732
    332680
    27626
    107430
    50936
    201250];

如何对它们进行排序,以便矩阵 B 的第 1 列包含向量 A2 的第 1 行中的项目的数据,矩阵 B 的第 2 列包含向量 A2 的第 2 行中的项目的数据,等等?

我非常粗略的解决方案如下:

A=A'; A2=A2';

for i=1:size(A,2)
    A(2:size(B,1)+1,i)=B(:,i);
end

A2(2:size(B,1)+1,:)=zeros(size(B,1),size(B,2));

for i=size(A2,2)
    for j=size(A,2)
        if A2(1,i)==A(1,j)
            A2(2:end,i)=A(2:end,j);
        end
    end
end

B2 = A2(2:end,:);

但我想知道一种更清洁、更优雅、更省时的方法。

【问题讨论】:

    标签: matlab sorting matrix


    【解决方案1】:

    一个可能的解决方案

    您可以使用ismember 函数的第二个输出。

    [~ ,idx] = ismember(A2,A);
    B2 = B(:,idx);
    

    更新:我测试了我的解决方案和hbaderts提出的另一个解决方案

    disp('-----ISMEMBER:-------')
    tic
        [~,idx]=ismember(A2,A);
    toc
    disp('-----SORT:-----------')
    tic
        [~,idx1] = sort(A);
        [~,idx2] = sort(A2);
        map = zeros(1,size(idx2));
        map(idx2) = idx1;
    toc
    

    这是 Octave 的结果:

    -----ISMEMBER:-------
    Elapsed time is 0.00157714 seconds.
    -----SORT:-----------
    Elapsed time is 4.41074e-05 seconds.
    

    结论排序方法效率更高!

    【讨论】:

    • 哇!这也是一个非常酷的解决方案。清晰,简洁,切中要害。顺便说一句,你怎么记得所有这些无数功能有多少输出?更重要的是,你如何在正确的时刻回忆起它们? :)
    • 在我在文档中看到它之前。但是在回答问题之前,我在命令提示符中使用了help ismember 并重新检查了文档!
    • @Kristada673 答案已更新,您可以接受另一个答案!
    • 哇,感谢有趣的编辑。我还尝试了随机的AA2,每个元素有 100000 个元素(randperm(100000)),结果分别为 0.32 秒和 0.21 秒。所以sort 仍然更快,但不是很多。我不介意您的答案是否仍然是公认的答案 - 两种解决方案都运作良好,而且速度并不总是主要标准。
    • 改变idx的位置B2 = B( idx, :) ;
    【解决方案2】:

    由于AA2 包含完全相同的元素,只是排序不同,我们可以创建从A-排序到A2-排序的映射。为此,我们在两者上运行 sort 函数并保存索引(这是第二个输出)。

    [~,idx1] = sort(A);
    [~,idx2] = sort(A2);
    

    现在,idx1 中的第一个元素对应于idx2 中的第一个元素,因此A(idx1(1))A2(idx2(1)) 相同(即27626)。为了创建一个映射idx1 -> idx2,我们使用矩阵索引如下

    map = zeros(size(idx2));
    map(idx2) = idx1;
    

    要对B进行相应的排序,我们需要做的就是

    B2 = B(:, map);
    

    【讨论】:

      【解决方案3】:
      [A2, sort_order] = sort(A);
      B2 = B(:, sort_order)
      

      MATLAB 的 sort 函数返回 A 中项目的排序顺序。您可以使用它对 B 中的列进行排序。

      【讨论】:

      • 但这会按升序对项目 ID 进行排序并存储在 A2 中。这不是我想做的。我已经以某种有意义的预定义顺序拥有A2
      【解决方案4】:

      转置B,以便您可以将其与A 连接:

      C = [A B']
      

      现在你有

      C = [ 50936  0  0  1  1  0  0  0  0;
           332680  0  0  0  0  0  0  0  0;
           107430  0  0  1  1  1  0  0  0;
           167940  0  0  0  0  0  0  0  0;
           185820  0  0  0  0  0  0  0  0;
            99732  0  0  1  1  0  0  0  0;
           198490  0  0  0  0  0  0  0  0;
           201250  0  0  1  1  1  1  0  0;
            27626  0  0  1  1  0  0  0  0;
            69375  0  0  1  1  1  0  0  1];
      

      您现在可以根据需要对矩阵的行进行排序。例如,要按 ID 升序排序,请使用sortrows

      C = sortrows(C)
      

      要交换行,请使用1:length(A) 的排列:

      C = C(perm, :)
      

      其中perm 可能类似于[4 5 6 3 2 1 8 7 9 10]

      这样,您的信息全部包含在一个结构中,并且数据始终与正确的 ID 正确匹配。

      【讨论】:

        猜你喜欢
        • 2016-10-27
        • 2014-07-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-09
        • 1970-01-01
        相关资源
        最近更新 更多