【问题标题】:MATLAB Sort 2D and 3D matrix and access through indexMATLAB 对 2D 和 3D 矩阵进行排序并通过索引访问
【发布时间】:2011-08-04 08:33:59
【问题描述】:

假设你有一个一维矩阵

a = rand(1,5);
[sa i] = sort(a);

那么saa(i) 是一样的。但是,如果矩阵的大小增加

a = rand(3,4);
[sa i] = sort(a);

那么saa(i) 就不一样了。当我尝试按第三维对 3D 矩阵进行排序时,也会发生同样的情况。

如何通过索引i 访问a 的值?或者换句话说,我如何计算sa=a(X)X 应该是什么?

编辑:

感谢您的解决方案。但是,当您更改要排序的维度时,它们不起作用。尽管如此,我还是接受了这个想法并用它来构建一个通用形式。

算法所做的是建立矩阵的索引。 MATLAB 按列索引单元格。因此,索引由下式给出

idx = r + (c-1)*ROWS + (p-1)*ROWS*COLS

其中,idx 是索引,r 是行位置,c 是列位置,p 是页面位置。

因此,如果我们在第一维排序(正常sort(a)),结果索引是列中的位置;如果我们在第二维排序,结果索引是行中的位置;如果我们在第三维排序,结果索引就是页面位置。话虽这么说,它只会持续为给定案例生成行和列:

r = repmat((1:rows)',[1 cols pages]);
c = repmat(1:cols,[rows 1 pages]);

在给定的解决方案中解释了第一维中的排序。然后,让我们对二维数组的第二维(按行)进行排序

a = rand(4,5);
[rows cols pages] = size(a);
R = repmat((1:rows)',[1 cols pages]);
[sa idx] = sort(a,2);
nIdx = R + (idx-1)*rows;
isequal(sa,a(nIdx))

现在,如果我们使用相同的想法在第三维(按页面)排序,我们需要这样做

a = rand(4,5,3);
[rows cols pages] = size(a);
R = repmat((1:rows)',[1 cols pages]);
C = repmat(1:cols,[rows 1 pages]);
[sa idx] = sort(a,3);
nIdx = R + (C-1)*rows + (idx-1)*rows*cols;
isequal(sa,a(nIdx))

并且可以使用相同的逻辑将其扩展到N维。 感谢您的帮助,您照亮了道路。 :)

【问题讨论】:

  • 2D 和 3D 的最佳答案就在这里。

标签: matlab sorting matrix indexing


【解决方案1】:

[sa, i]=sort(a) 返回每​​列的有序索引。您只需要获取矩阵的正确线性索引。所以,对于一个二维矩阵,

A=rand(3,4);
[rows,cols]=size(A);
[B,index]=sort(A,1);
correctedIndex=index+repmat(0:cols-1,rows,1)*rows;

现在测试一下:

A =

    0.9572    0.1419    0.7922    0.0357
    0.4854    0.4218    0.9595    0.8491
    0.8003    0.9157    0.6557    0.9340

B =

    0.4854    0.1419    0.6557    0.0357
    0.8003    0.4218    0.7922    0.8491
    0.9572    0.9157    0.9595    0.9340

A(correctedIndex)

ans =

    0.4854    0.1419    0.6557    0.0357
    0.8003    0.4218    0.7922    0.8491
    0.9572    0.9157    0.9595    0.9340

【讨论】:

  • 此外,您还可以查看sortrows 函数,其第二个输出参数可用于实现类似sa=a(i,:) 的内容,使用您的符号。
  • 谢谢,你把我引向了正确的方向。我知道如何使用索引。我扩展了您的解决方案,使其适用于任何维度的排序。谢谢
【解决方案2】:

您可以使用函数IND2SUBSUB2IND 创建适用于任何 N 维矩阵或排序维度的通用矢量化解决方案。在这里,我把这个解决方案打包成一个新函数sort_linear_index,它的行为就像函数SORT,只是它会返回线性索引,这样B = A(IX) 将始终有效,无论A 是什么大小.

function [sortedA,sortIndex] = sort_linear_index(A,sortDim,sortOrder)
%#SORT_LINEAR_INDEX   Just like SORT, but returns linear indices

  sizeA = size(A);  %# Get the matrix size
  if nargin < 2
    sortDim = find(sizeA > 1,1);  %# Define sortDim, if necessary
  end
  if nargin < 3
    sortOrder = 'ascend';  %# Define sortOrder, if necessary
  end
  [sortedA,sortIndex] = sort(A,sortDim,sortOrder);  %# Sort the matrix
  [subIndex{1:numel(sizeA)}] = ...  %# Create a set of matrix subscripts
     ind2sub(sizeA,reshape(1:prod(sizeA),sizeA));
  subIndex{sortDim} = sortIndex;  %# Overwrite part of the subscripts with
                                  %#   the sort indices
  sortIndex = sub2ind(sizeA,subIndex{:});  %# Find the linear indices

end

现在我们可以测试这个功能了:

>> A = rand(1,10);
>> [B,IX] = sort_linear_index(A);  %# Sort a row vector
>> isequal(B,A(IX))
ans =
     1
>> A = rand(3,4,3);
>> [B,IX] = sort_linear_index(A,1);  %# Sort a 3-by-4-by-3 matrix along
>> isequal(B,A(IX))                  %#   the first dimension
ans =
     1
>> [B,IX] = sort_linear_index(A,3);  %# Sort a 3-by-4-by-3 matrix along
>> isequal(B,A(IX))                  %#   the third dimension
ans =
     1
>> [B,IX] = sort_linear_index(A,2,'descend');  %# Sort a 3-by-4-by-3 matrix along
>> isequal(B,A(IX))                            %#   the second dimension
ans =                                          %#   in descending order
     1

【讨论】:

    【解决方案3】:
    a = rand(3,5);
    [sa i] = sort(a);
    ii=bsxfun(@plus,i,0:size(a,1):numel(a)-size(a,1));
    isequal(a(ii),sa)
    

    【讨论】:

      【解决方案4】:

      从这里:http://www.mathworks.com/help/techdoc/ref/sort.html

      sa(:,j) = a(i(:,j),j)
      

      【讨论】:

      • 是的,我使用了循环操作。但是,我想知道仅使用矩阵运算或索引是否有一些技巧,因为它们更快。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-27
      • 2018-06-01
      • 2015-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多