Select first n nonzero elements in each row of matrix

조회 수: 25 (최근 30일)
giometar
giometar 2020년 6월 23일
편집: giometar 2020년 6월 25일
Hello
How to select first n nonzero elements from each row?
If I have matrix A, and I want result like B (three nonzero elements from each row):
Rusult also can be cell..
A=[1 3 0 2 5
0 2 0 1 0
2 0 0 0 0
3 1 1 0 0];
B=[1 3 2
2 1 0
2 0 0
3 1 1];

채택된 답변

Stephen23
Stephen23 2020년 6월 24일
편집: Stephen23 2020년 6월 24일
Linear indexing does this simply and efficiently. The trick is to work down the columns, which requires transposing:
>> A = [1,3,0,2,5;0,2,0,1,0;2,0,0,0,0;3,1,1,0,0]
A =
1 3 0 2 5
0 2 0 1 0
2 0 0 0 0
3 1 1 0 0
>> N = 3;
>> Z = A.';
>> S = size(Z);
>> [~,R] = sort(Z==0,1);
>> [~,C] = ndgrid(1:N,1:S(2));
>> X = sub2ind(S,R(1:N,:),C);
>> B = Z(X).'
B =
1 3 2
2 1 0
2 0 0
3 1 1
Probably the most efficient approach would be to use a simple loop, e.g. (not particularly optimized):
R = size(A,1);
B = zeros(R,N);
for k = 1:R
tmp = nonzeros(A(k,:));
idx = 1:min(N,numel(tmp));
B(k,idx) = tmp(idx);
end
Some timings (1e3 iterations):
Elapsed time is 5.358 seconds. % madhan ravi's with loop and CELLFUN
Elapsed time is 0.606 seconds. % my answer with SUB2IND
Elapsed time is 0.265 seconds. % my answer with loop and indexing

추가 답변 (1개)

madhan ravi
madhan ravi 2020년 6월 23일
편집: madhan ravi 2020년 6월 23일
ix = cumprod(A ~= 0, 2);
B = A(:, max(ix) ~= 0)
%OR
ix = cumprod(A ~= 0, 2); % remove cumprod(...) if you don't expect n consecutive nonzero elements
n = 3;
idx = find(cumsum(ix,2) == n, 1);
[~, c] = ind2sub(size(A), idx);
B = A(:, 1:c)
% OR
% if you don't want to specify n by yourself
ix = cumprod(A ~= 0, 2); % remove cumprod(...) if you don't expect n consecutive nonzero elements
ix1 = cumsum(ix,2);
idx = find(ix1 == max(max(ix1)), 1); % use max(..., [], 'all') for later versions
[~, c] = ind2sub(size(A), idx);
B = A(:, 1:c)
  댓글 수: 3
madhan ravi
madhan ravi 2020년 6월 23일
편집: madhan ravi 2020년 6월 23일
n = 3; % n non-zero elements
B = cell(size(A,1),1);
for k = 1:size(A,1)
B{k} = nonzeros(A(k,:)).';
end
B = cellfun(@(x) x(1:numel(x) < n+1), B, 'un', 0);
B = cell2mat(cellfun(@(x) [x, zeros(1, n-numel(x))], B, 'un',0))
giometar
giometar 2020년 6월 25일
편집: giometar 2020년 6월 25일
Thanks madhan ravi for help. Your solution is also warking but solution from
Stephen Cobeldick is better for me

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Graphics Object Programming에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by