保持最大和最大Matlab中矩阵每行中的最小元素

时间:2016-05-20 21:25:10

标签: matlab matrix indexing

我试图使用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]

我和sort一起尝试ismember但没有运气。

我怎样才能保持最大的&输入矩阵每行中的最小元素,并删除每行中的其余元素?

2 个答案:

答案 0 :(得分:2)

有一种非常优雅的方法可以做到这一点。我们需要使用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

答案 1 :(得分:1)

这是使用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