繁体   English   中英

在矩阵的每一行中找到前N个非零元素

[英]Find the first N non-zero elements in each row of a matrix

我在MATLAB中有一个零的矩阵,我想在每行中得到前N个非零元素的另一个矩阵。 假设例如N = 3 ,而矩阵为

A = [ 0 0 2 0 6 7 9;
      3 2 4 7 0 0 6;
      0 1 0 3 4 8 6;
      1 2 0 0 0 1 3]

我希望结果是:

B = [2 6 7;
     3 2 4;
     1 3 4;
     1 2 1]

我有一个巨大的矩阵,所以我想不加循环地进行操作,您能帮我吗? 非常感谢!

由于MATLAB根据列的主要顺序存储矩阵,因此我首先转置A ,使非零冒泡,然后选择前N条线,然后转置回去:

N = 3;
A = [ 0 0 2 0 6 7 9;
      3 2 4 7 0 0 6;
      0 1 0 3 4 8 6;
      1 2 0 0 0 1 3];

转置并预分配输出B

At = A';
B = zeros(size(At));

At =
     0     3     0     1
     0     2     1     2
     2     4     0     0
     0     7     3     0
     6     0     4     0
     7     0     8     1
     9     6     6     3

索引零

idx = At == 0;

idx =
     1     0     1     0
     1     0     0     0
     0     0     1     1
     1     0     0     1
     0     1     0     1
     0     1     0     0
     0     0     0     0

冒泡非零

B(~sort(idx)) = At(~idx);

B =
     2     3     1     1
     6     2     3     2
     7     4     4     1
     9     7     8     3
     0     6     6     0
     0     0     0     0
     0     0     0     0

选择前N行并转置回去

B(1:N,:)'

您可以按行优先的顺序进行冒泡,但是您需要使用find检索行和列下标,并在那里进行一些排序和选择。 它变得更加乏味且可读性较差。

使用没有循环的accumarray

N = 3;
[ii,jj] = find(A); [ii,inds]=sort(ii); jj = jj(inds);
lininds = ii+size(A,1)*(jj-1);
C = accumarray(ii,lininds,[],@(x) {A(x(1:N)')}); %' cell array output
B = vertcat(C{:})
B =
     2     6     7
     3     2     4
     1     3     4
     1     2     1

通常我不使用for循环解决方案,但这很直观:

N = 3;
[ii,jj] = find(A);
B = zeros(size(A,1),N);
for iRow = 1:size(A,1),
    nzcols = jj(ii==iRow);
    B(iRow,:) = A(iRow,nzcols(1:N));
end

由于可以保证A每行有N非零,所以应该可以完成工作。

N = 3;
for ii=1:size(A,1);
    B(ii,:) = A( ii,find(A(ii,:),N) );
end

一线解决方案:

B = cell2mat(cellfun(@(c) c(1:N), arrayfun(@(k) nonzeros(A(k,:)), 1:size(A,1), 'uni', false), 'uni', false)).'

不是非常优雅或高效,而是非常有趣!

实际上,您可以像代码打击一样做到这一点:


N=3
 for n=1:size(A,1)
   [a b]=find(A(n,:)>0,N);
   B(n,:)=A(n,transpose(b));
end

然后我认为这个B矩阵将是您想要的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM