Select first n nonzero elements in each row of matrix

16 ビュー (過去 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 件のコメント
giometar
giometar 2020 年 6 月 25 日
Thank you very much for help.

サインインしてコメントする。

その他の回答 (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

サインインしてコメントする。

Community Treasure Hunt

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

Start Hunting!

Translated by