我试图使用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
但没有运气。
我怎样才能保持最大的&输入矩阵每行中的最小元素,并删除每行中的其余元素?
答案 0 :(得分:2)
有一种非常优雅的方法可以做到这一点。我们需要使用sort
的第二个输出,它给出了特定维度上元素的顺序。需要注意的是,它给了我们所需要的反置换,因此我们必须递归地重复两次。我们所需要的是使用逻辑索引将所有那些索引超过2
且小于size(A,1)-1
的元素设置为零。
另外,请注意,使用数字矩阵更容易,而不是像示例中那样使用单元格。如果需要,您可以使用cell2mat
和num2cell
来回转换。
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