使用自定义排序顺序的多键`table / sortrows`

时间:2014-02-14 21:01:22

标签: matlab sorting

如何使用某些排序列的自定义(即非标准)排序顺序对表行进行排序?

例如,下面的显示会显示sortrows的输出,其中包含所有排序列的标准排序顺序:

>> sortrows(A, {'TrafficLight', 'Suit', 'Parity'})
ans = 
    Parity    TrafficLight      Suit      order    prevalence
    ______    ____________    ________    _____    __________
    even      'green'         hearts      49       0.5025    
    even      'green'         hearts      64       0.5318    
    even      'green'         hearts      67       0.7896    
    odd       'green'         hearts       4       0.6374    
    odd       'green'         hearts      11       0.3354    
    odd       'green'         hearts      59       0.8644    
    even      'green'         spades      35       0.6674    
    odd       'green'         spades      64       0.4348    
    even      'red'           diamonds    69       0.5751    
    even      'red'           diamonds    77       0.6318    
    even      'red'           diamonds    89       0.2629    
    even      'red'           diamonds    92       0.2596    
    even      'red'           diamonds    98       0.3578    
    odd       'red'           diamonds    69       0.2911    
    odd       'red'           diamonds    74       0.3343    
    even      'red'           hearts      19       0.5695    
    odd       'red'           hearts      51       0.9122    
    even      'red'           spades      38       0.9837    
    odd       'red'           spades      22       0.5587    
    even      'yellow'        clubs       22       0.6917    
    odd       'yellow'        diamonds     1       0.2064    
    odd       'yellow'        diamonds    25       0.8257    
    odd       'yellow'        spades      33       0.2653    
    odd       'yellow'        spades      38       0.2549    

但我们假设我希望TrafficLight值的排序顺序为

'red' < 'yellow' < 'green'

Suit值为

的那个
diamonds < hearts < clubs < spades

Parity保持不变的原因。

  

如何重新排序A行,以便新排序反映这些自定义排序顺序?

(当然,行的重新排序必须遵守原始调用sortrows中指定的排序键优先级,即'TrafficLight' < 'Suit' < 'Parity'。)


PS:生成A的代码:

kvs = {'Parity', 'TrafficLight', 'Suit'};
A = cell2table({
                'odd', 'yellow', 'diamonds', 1, 0.2064;
                'odd', 'green', 'hearts', 4, 0.6374;
                'odd', 'green', 'hearts', 11, 0.3354;
                'even', 'red', 'hearts', 19, 0.5695;
                'even', 'yellow', 'clubs', 22, 0.6917;
                'odd', 'red', 'spades', 22, 0.5587;
                'odd', 'yellow', 'diamonds', 25, 0.8257;
                'odd', 'yellow', 'spades', 33, 0.2653;
                'even', 'green', 'spades', 35, 0.6674;
                'even', 'red', 'spades', 38, 0.9837;
                'odd', 'yellow', 'spades', 38, 0.2549;
                'even', 'green', 'hearts', 49, 0.5025;
                'odd', 'red', 'hearts', 51, 0.9122;
                'odd', 'green', 'hearts', 59, 0.8644;
                'even', 'green', 'hearts', 64, 0.5318;
                'odd', 'green', 'spades', 64, 0.4348;
                'even', 'green', 'hearts', 67, 0.7896;
                'even', 'red', 'diamonds', 69, 0.5751;
                'odd', 'red', 'diamonds', 69, 0.2911;
                'odd', 'red', 'diamonds', 74, 0.3343;
                'even', 'red', 'diamonds', 77, 0.6318;
                'even', 'red', 'diamonds', 89, 0.2629;
                'even', 'red', 'diamonds', 92, 0.2596;
                'even', 'red', 'diamonds', 98, 0.3578
               }, 'VariableNames', ...
               [kvs {'order', 'prevalence'}]);
A.Parity = categorical(A.Parity);
A.Suit = categorical(A.Suit);

2 个答案:

答案 0 :(得分:2)

我正在回答Cell,因为我的Matlab不支持表格。

%define an order:
colororder=@(x)(strcmp(x,'red')+strcmp(x,'yellow')*2+strcmp(x,'green')*3)
%get sorted indices
[~,ix]=sort(colororder(A(:,2)))
%sort:
A(ix,:)

也许你也可以将它应用于表格。对于Enums来说这将是一项不错的任务,但Matlab不支持Enums。

答案 1 :(得分:2)

我也在回答细胞,原因和丹尼尔一样。

我的方法:

  1. 定义每个密钥的顺序。
  2. 按顺序索引替换字符串。您可以使用ismember
  3. 的第二个输出轻松完成此操作
  4. 使用所需的排序键优先顺序对替换字符串数组进行排序。存储sort的第二个输出,它告诉重新排序与排序相对应的行。
  5. 将该重新排序应用于原始数组的行。

    parityOrder = {'even','odd'}; %// step 1
    colorOrder = {'red','yellow','green'};
    suitOrder = {'diamonds','hearts','clubs','spades'};
    
    [~, p] = ismember(A(:,1),parityOrder); %// step 2
    [~, c] = ismember(A(:,2),colorOrder);
    [~, s] = ismember(A(:,3),suitOrder);
    
    [~, ii] = sortrows([p c s],[2 3 1]); %// step 3
    
    result = A(ii,:); %// step 4