Select first n nonzero elements in each row of matrix

13 Ansichten (letzte 30 Tage)
giometar
giometar am 23 Jun. 2020
Bearbeitet: giometar am 25 Jun. 2020
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];

Akzeptierte Antwort

Stephen23
Stephen23 am 24 Jun. 2020
Bearbeitet: Stephen23 am 24 Jun. 2020
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

Weitere Antworten (1)

madhan ravi
madhan ravi am 23 Jun. 2020
Bearbeitet: madhan ravi am 23 Jun. 2020
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 Kommentare
madhan ravi
madhan ravi am 23 Jun. 2020
Bearbeitet: madhan ravi am 23 Jun. 2020
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 am 25 Jun. 2020
Bearbeitet: giometar am 25 Jun. 2020
Thanks madhan ravi for help. Your solution is also warking but solution from
Stephen Cobeldick is better for me

Melden Sie sich an, um zu kommentieren.

Community Treasure Hunt

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

Start Hunting!

Translated by