【问题标题】:Keep largest & smallest elements in each row of a matrix in Matlab在 Matlab 中保留矩阵的每一行中的最大和最小元素
【发布时间】:2016-09-18 06:35:33
【问题描述】:

我正在尝试使用 Matlab 在矩阵的每一行中保留最高和最低值。例如,我有初始矩阵:

A=
[-6 1   3   9   2   -1;
3   -3  6   5   0   -8;
5   10  9   3   2   1;
20  2   -1  4   9   -4;
4   6   -2  2   7   9;
10  5   -3  3   1   4]

并且我需要在矩阵的每一行中保留最大和最小的元素(假设 2 个最大和 2 个最小),以便最终矩阵如下所示:

B=
[-6 0   3   9   0   -1;
0   -3  6   5   0   -8;
0   10  9   0   2   1;
20  0   -1  0   9   -4;
0   0   -2  2   7   9;
10  5   -3  0   1   0]

我尝试了sortismember,但没有任何运气。

如何在输入矩阵的每一行中保留最大和最小元素,并删除每一行中的其余元素?

【问题讨论】:

  • 我刚刚提交了对问题的编辑,因此希望能够通过并且问题的意图更加清晰。话虽这么说,@Sardar_Usama 我相信你是对的 - 他们希望在矩阵的每一行中保留最高和最低值,并删除每一行中的其余值。在 OP 提供的示例最终矩阵中,矩阵每行中的 2 个最大和 2 个最小值被保留,而每行中的其余值被替换为 0。

标签: matlab matrix indexing


【解决方案1】:

有一种非常优雅的方法可以做到这一点。我们需要使用sort 的第二个输出,它给出了元素在特定维度上的顺序。需要注意的是,它给了我们所需的逆排列,所以我们必须递归地重复两次。然后,我们只需使用逻辑索引将所有索引大于2 且小于size(A,1)-1 的元素设置为零。

另外,请注意使用数字矩阵要容易得多,而不是像您的示例中那样使用单元格。如果需要,可以使用cell2matnum2cell 来回转换。

A = [-6, 1, 3, 9, 2, -1; ...
    3, -3, 6, 5, 0, -8; ...
    5, 10, 9, 3, 2, 1; ...
    20, 2, -1, 4, 9, -4; ...
    4, 6. -2, 2, 7, 9; ...
    10, 5, -3, 3, 1, 4];

[~, idx_inv] = sort(A,2);
[~, idx] = sort(idx_inv,2);
toRemove = idx>2 & (idx<size(A,1)-1);
B = A; B(toRemove) = 0;

>> B
B =
    -6     0     3     9     0    -1
     0    -3     6     5     0    -8
     0    10     9     0     2     1
    20     0    -1     0     9    -4
     0     0    -2     2     7     9
    10     5    -3     0     1     0

编辑将性能与@luis-mendo 建议的选项进行比较:

K>> tic; for t = 1:1e6, [~, idx_inv] = sort(A,2); [~, idx] = sort(idx_inv,2); B = A; B(idx>2 & (idx<size(A,1)-1)) = 0; end; toc;
Elapsed time is 12.379617 seconds.

K>> tic; for t = 1:1e6, s = sum(bsxfun(@gt, A, permute(A, [1 3 2])), 3); B = A.*(s<2 | s>size(A,2)-3); end; toc;
Elapsed time is 17.630724 seconds.

这个使用sort 的解决方案似乎快了~1.42x

【讨论】:

    【解决方案2】:

    这是使用bsxfun 的另一种方法。可能效率不高。

    让你的数据定义为:

    A = [ -6     1     3     9     2    -1
           3    -3     6     5     0    -8
           5    10     9     3     2     1
          20     2    -1     4     9    -4
           4     6    -2     2     7     9
          10     5    -3     3     1     4 ];
    m = 2;
    M = 2;
    

    然后:

    s = sum(bsxfun(@gt, A, permute(A, [1 3 2])), 3);  % for each element, compute how many
                                                      % elements in its row it exceeds
    result = A.*(s<m | s>size(A,2)-M-1);              % apply a mask based on that
    

    【讨论】:

    • 有趣的方法,但似乎速度较慢。在我的答案中添加了性能比较。
    • @nirvana-msu 是的,正如我在回答中所写的那样,我没想到它会非常有效。但是在这里使用bsxfun 太诱人了:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-13
    • 2014-04-08
    • 1970-01-01
    • 2012-12-10
    • 1970-01-01
    相关资源
    最近更新 更多