【问题标题】:Sorting data in MATLAB dependant on one column在 MATLAB 中根据一列对数据进行排序
【发布时间】:2015-09-16 15:10:17
【问题描述】:

如何根据 MA​​TLAB 中另一列中的值对列进行排序?

A 列显示位置数据(按升序或降序排列)B 列包含另一列位置数据。最后列C 包含数值。是否可以将B 中的第一个位置值与C 的第一个单元格中的数值链接?然后在此之后我想对B 进行排序,使其与A 列的顺序相同,C 值跟在它们的B 对应项之后?我的列的长度将是 1558 个值。

大小写之前;

A     B     C
1      4      10
4      1      20
3      5      30
5      2      40
2      3      50

事后;

A     B     C
1      1      20
4      4      10
3      3      50
5      5      30
2      2      40

基本上AB 变为相同,列C 跟随B

【问题讨论】:

    标签: matlab sorting


    【解决方案1】:

    由于您不希望事物必须按升序或降序排列,因此我认为像 sortrows() 这样的任何内置排序功能都不会在这里有所帮助。相反,您将一列中的元素与另一列中的元素匹配。

    使用[~,idx]=ismember(A,B) 将告诉您B 的每个元素在A 中的位置。您可以使用它对所需的列进行排序。

    M=[1      4      10
       4      1      20
       3      5      30
       5      2      40
       2      3      50];
    A=M(:,1); B=M(:,2); C=M(:,3);
    [~,idx]=ismember(A,B); 
    
    sorted_matrix = [A B(idx) C(idx)]
    

    【讨论】:

    • 很好地使用ismember 我忘了它也返回位置。很好的解决方案,因为它可以处理所有错误。
    • 如果 A 列中的某些值为负数,我该如何实现
    • @Jerry 您的评论帮助我发现了原始解决方案中的错误。它现在已修复,即使 A 中的负条目也应该可以工作(假设 B 中有相应的负条目)。
    • @Geoff 我在使用%Create matrix% Matrix = [Control, LES2_54_pos, LES2_54_U]; %Sort Matrix% A=Matrix(:,1); B=Matrix(:,2); C=Matrix(:,3); [~,idx]=ismember(A,B); sorted_matrix = [A B(idx) C(idx)] 时仍然遇到同样的错误我不确定它是否相关,但在排序之前 A 中的负值与 B 中的负值不匹配。因此,为什么需要排序。
    • @Jerry 那么,M=[-1 4 10 4 1 20 -3 -5 30 5 -2 40 2 3 50] 的输出必须是什么?用这种情况编辑您的问题?
    【解决方案2】:

    bsxfunmatrix-multiplication 的强大组合解决了这个问题,并且对 code-golfing 也有好处!这是实现,假设M作为输入矩阵-

    [M(:,1) bsxfun(@eq,M(:,1),M(:,2).')*M(:,2:3)]
    

    示例运行 -

    >> M
    M =
         1     4    10
         4     1    20
         3     5    30
         5     2    40
         2     3    50
    >> [M(:,1) bsxfun(@eq,M(:,1),M(:,2).')*M(:,2:3)]
    ans =
         1     1    20
         4     4    10
         3     3    50
         5     5    30
         2     2    40
    

    【讨论】:

    • 为什么在我使用此代码时包含*M(:,2:3),它对矩阵进行排序,但我的原始值被相乘,现在给我的值不正确
    【解决方案3】:

    给定M = [A B C]

    M =
    
        1    4   10
        4    1   20
        3    5   30
        5    2   40
        2    3   50
    

    您需要对矩阵的行进行排序排除第一列:

    s = sortrows(M(:,2:3));
    
    s =
    
        1   20
        2   40
        3   50
        4   10
        5   30
    

    然后使用第一列作为索引对生成的子矩阵重新排序:

    s(M(:,1),:);
    
    ans =
    
        1   20
        4   10
        3   50
        5   30
        2   40
    

    这将用于构建输出矩阵:

    N = [M(:,1) s(M(:,1),:)];
    
    N =
    
        1    1   20
        4    4   10
        3    3   50
        5    5   30
        2    2   40
    

    显然只有当AB 是值(1..m) 的排列时,前面的技术才有效。如果不是这样,那么我们需要找到数组中每个值的排名。让我们从数组的新值开始:

        A    B   C
        1    5   60
        6    1   80
        9    6   60
       -4    9   40
        5   -4   30
    

    我们像以前一样构造s

    s = sortrows([B C]);
    
    s =
    
       -4   30
        1   80
        5   60
        6   60
        9   40
    

    我们可以通过以下两种方式之一生成排名。如果A(和B)的元素是唯一的,我们可以使用unique的第三个输出,如this answer

    [~, ~, r] = unique(A);
    
    r =
    
       2
       4
       5
       1
       3
    

    如果A 的值不是唯一的,我们可以使用 sort 的第二个返回值,即按排序顺序排列的元素在原始数组中的索引,来生成每个元素的排名元素:

    [~, r] = sort(A);
    
    r =
    
       4
       1
       5
       2
       3
    
    [~, r] = sort(r);
    
    r =
    
       2
       4
       5
       1
       3
    

    如您所见,生成的 r 是相同的,它只需要 2 次调用 sort 而不是 1 次调用 unique。然后我们使用r 作为上面s 的索引列表:

    M = [A s(r, :)];
    
    M =
    
        1    1   80
        6    6   60
        9    9   40
       -4   -4   30
        5    5   60
    

    【讨论】:

    • 如果 A 列中的某些数字为负数,我该如何实现?
    【解决方案4】:

    如果您必须保留A 的顺序,请使用类似这样的内容

    matrix = [1 4 10; 4 1 20; 3 5 30; 5 2 40; 2 3 50];
    idx = arrayfun(@(x) find(matrix(:,2) == x), matrix(:,1));
    sorted = [matrix(:,1), matrix(idx,2:3)];
    

    【讨论】:

    • 您能否解释为什么我收到以下错误 Error using arrayfun Non-scalar in Uniform output, at index 1, output 1. 将“UniformOutput”设置为 false。 Sort_data 中的错误(第 14 行) idx = arrayfun(@(x) find(Matrix(:,2) == x), Matrix(:,1));
    • 我猜这是因为您在第 2 列中有重复的值。如果这是真的,您需要确定要保留哪一个。如果是第一个,则更改为find(matrix(:,2) == x, 1, 'first')
    • @Jerry 如果您对AB 列的任一列有重复值,您将得到一个不平衡的答案。如果B 中有重复值,这意味着您至少有 1 个空的A 条目,第 3 行将出错。此外,您至少有 2 行 B 将匹配 A。听起来你需要事先清理你的号码。如果所有 3 列都相同,您可以使用 uniquerows 选项。如果不是,您需要使用一些选择标准,例如 max/min C
    猜你喜欢
    • 2015-08-21
    • 2013-02-10
    • 1970-01-01
    • 1970-01-01
    • 2021-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-06
    相关资源
    最近更新 更多