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

后端 未结 6 1500
误落风尘
误落风尘 2020-12-21 08:02

I have a matrix in MATLAB with zeroes and I would like to get another matrix with the first N non-zero elements in each row. Let\'s say for example N = 3<

相关标签:
6条回答
  • 2020-12-21 08:13
    N = 3;
    for ii=1:size(A,1);
        B(ii,:) = A( ii,find(A(ii,:),N) );
    end
    
    0 讨论(0)
  • 2020-12-21 08:16

    Since MATLAB stores a matrix according to column-major order, I first transpose A, bubble up the non-zeros, and pick the first N lines, and transpose back:

    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];
    

    Transpose and preallocate output 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
    

    Index zeros

    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
    

    Bubble up the non-zeros

    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
    

    Select first N rows and transpose back

    B(1:N,:)'
    

    You can do the bubbling in row-major order, but you would need to retrieve the row and column subscripts with find, and do some sorting and picking there. It becomes more tedious and less readable.

    0 讨论(0)
  • 2020-12-21 08:17

    One-liner solution:

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

    Not terribly elegant or efficient, but so much fun!

    0 讨论(0)
  • 2020-12-21 08:23

    Actually , you can do it like the code blow:


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

    Then I think this B matrix will be what you want.

    0 讨论(0)
  • 2020-12-21 08:24

    Usually I don't go with a for loop solution, but this is fairly intuitive:

    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
    

    Since you are guaranteed to have more than N nonzeros per row of A, that should get the job done.

    0 讨论(0)
  • 2020-12-21 08:37

    Using accumarray with no loops:

    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
    
    0 讨论(0)
提交回复
热议问题