I have a matrix. I want to count number of only those zeros which are lying between 2 sets of consecutive nonzero values on each side. How to do? Desired result given below

6 ビュー (過去 30 日間)
d=[0 0 3 4 1 0 7 8;6 8 0 4 5 1 0 0;0 0 0 0 0 0 0 2;2 0 0 4 5 0 6 4;7 2 0 0 2 1 0 0;12 6 0 0 0 4 8 2];
desired_no_of_zeros=[1;1;0;1;2;3]
  4 件のコメント
Image Analyst
Image Analyst 2023 年 7 月 2 日
Exactly what does "between" mean when you are talking about a 2-D matrix? Do you mean totally surrounded on all sides? Or do you mean on a row-by-row basis, or a column-by column basis?

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

回答 (5 件)

DGM
DGM 2023 年 6 月 25 日
編集済み: DGM 2023 年 6 月 25 日
I'm sure this can be simplified. I just felt like using regexp() for this.
A = [0 0 3 4 1 0 7 8;
6 8 0 4 5 1 0 0;
0 0 0 0 0 0 0 2;
2 0 0 4 5 0 6 4;
7 2 0 0 2 1 0 0;
12 6 0 0 0 4 8 2];
% convert to cellchar
key = '01';
str = key((A~=0)+1);
str = num2cell(str,2);
% find runs of zeros between runs of nonzeros that are at least 2 elements long
C = regexp(str,'((?<=1{2,})(0+)(?=1{2,}))','match');
runl = zeros(numel(C),1);
for k = 1:numel(C)
runl(k) = numel([C{k}{:}]);
end
runl
runl = 6×1
1 1 0 1 2 3
  2 件のコメント
Payel
Payel 2023 年 6 月 25 日
Thanks will you please suggest how to simplify this a little bit
DGM
DGM 2023 年 6 月 25 日
編集済み: DGM 2023 年 6 月 25 日
A = [0 0 3 4 1 0 7 8;
6 8 0 4 5 1 0 0;
0 0 0 0 0 0 0 2;
2 0 0 4 5 0 6 4;
7 2 0 0 2 1 0 0;
12 6 0 0 0 4 8 2];
% convert to cellchar
key = '01';
str = key((A~=0)+1);
str = num2cell(str,2);
% find runs of zeros between runs of nonzeros that are at least 2 elements long
C = regexp(str,'((?<=1{2,})(0+)(?=1{2,}))','match');
runl = cellfun(@(x) numel([x{:}]),C)
runl = 6×1
1 1 0 1 2 3
That's a bit less verbose, though it's probably not faster.
For what it's worth, MattJ's answer may be of interest if speed is a critical concern and your input matrices are consistently large compared to this example (e.g. 100x100 or larger).

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


VM Sreeram
VM Sreeram 2023 年 6 月 25 日
d = [0 0 3 4 1 0 7 8; 6 8 0 4 5 1 0 0; 0 0 0 0 0 0 0 2; 2 0 0 4 5 0 6 4; 7 2 0 0 2 1 0 0; 12 6 0 0 0 4 8 2];
desired_no_of_zeros = zeros(size(d, 1), 1);
for row = 1:size(d, 1)
non_zero_indices = find(d(row, :) ~= 0); % Find indices of nonzero values
if numel(non_zero_indices) >= 2
first_non_zero = non_zero_indices(1);
last_non_zero = non_zero_indices(end);
desired_no_of_zeros(row) = sum(d(row, first_non_zero+1:last_non_zero-1) == 0);
end
end
desired_no_of_zeros
desired_no_of_zeros = 6×1
1 1 0 3 2 3
This code iterates over each row of the matrix d. For each row, it finds the indices of nonzero values. If there are at least two nonzero values, it calculates the number of zeros between them by summing the logical array d(row,first_non_zero+1:last_non_zero-1) == 0.

Jacob Mathew
Jacob Mathew 2023 年 6 月 25 日
Hi Payel,
If I understood the query correctly, the question is to find the longest number of zeros per row that are enclosed by non zero values. In that case the following algorithm will get it done:
  • Using a for loop to iterate over each row of the matrix
  • For every row, we will find the location of every non zero elements
  • We then check to make sure that there are at least 2 non zero elements per row else there will be no enclosed zeros
  • Then we iterate pair wise over the indices of non zero elements and calculate the length between indices. This is equivalent to finding the number of zeroes between non zero elements.
  • We finally find the maximum of the above step per row to find the longest length of zeros per row
Since we are using two for loops, the time complexity for this will be O()
An example code to implement this algorithm is as follows:
% matrix variable will be the input
matrix=[0 0 3 4 1 0 7 8;6 8 0 4 5 1 0 0;0 0 0 0 0 0 0 2;2 0 0 4 5 0 6 4;7 2 0 0 2 1 0 0;12 6 0 0 0 4 8 2];
% Initialising the output vector
longest_zero_counts = zeros(size(matrix, 1), 1);
% Iterate through each row to count the longest number of zeros
[rows, ~] = size(matrix);
longestZeroCount = zeros(rows, 1); % This will keep track of the longest zero number of zero per row
for i = 1:rows
row = matrix(i, :); % we take the row in question to calculate
nonZeroIndices = find(row ~= 0); % Find indices of non-zero numbers
if ~isempty(nonZeroIndices) && numel(nonZeroIndices) > 1 % checking if the are at least 2 non zero values in the row
for j = 2:numel(nonZeroIndices)
startIdx = nonZeroIndices(j-1);
endIdx = nonZeroIndices(j);
zeroCount = sum(row(startIdx+1:endIdx-1) == 0);
longestZeroCount(i) = max(longestZeroCount(i), zeroCount); % calculating the longest zero count
end
end
end
disp(longestZeroCount) % this will display the output vector with the solution
1 1 0 2 2 3
  1 件のコメント
Payel
Payel 2023 年 6 月 25 日
Thanks but the number of zero count in the fourth row must be 1 i.e. counting the zero which is in the 6th column only as it is bounded by 2 consecutive non zero values on each side i.e. 4 5 on left and 6 4 on right. How to do that?

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


Matt J
Matt J 2023 年 6 月 25 日
編集済み: Matt J 2023 年 6 月 25 日
Using this FEX download,
d=[0 0 3 4 1 0 7 8;
6 8 0 4 5 1 0 0;
0 0 0 0 0 0 0 2;
2 0 0 4 5 0 6 4;
7 2 0 0 2 1 0 0;
12 6 0 0 0 4 8 2];
[m,n]=size(d);
result=nan(m,1);
for i=1:m
[start,stop, Length]=groupLims( groupTrue(d(i,:)~=0) , 1);
start(Length<=1)=[]; stop(Length<=1)=[];
result(i)=sum( start(2:end) - stop(1:end-1) -1 )
end
>> result'
ans =
1 1 0 1 2 3

Stephen23
Stephen23 2023 年 6 月 26 日
A general solution requires that:
  • the 3rd value should be empty.
  • therefore e.g. a container array needs to be used.
Consider if there are N such sequences of zeros, then there would be N length values. Consider the bugs that would occur if you tried looping over "0", when in fact there is no such sequence in your data (it would require special-case handling). In contrast, simply storing N lengths works for an number of N.
d = [0,0,3,4,1,0,7,8; 6,8,0,4,5,1,0,0; 0,0,0,0,0,0,0,2; 2,0,0,4,5,0,6,4; 7,2,0,0,2,1,0,0; 12,6,0,0,0,4,8,2]
d = 6×8
0 0 3 4 1 0 7 8 6 8 0 4 5 1 0 0 0 0 0 0 0 0 0 2 2 0 0 4 5 0 6 4 7 2 0 0 2 1 0 0 12 6 0 0 0 4 8 2
[B,E] = regexp(cellstr(char('1'-~d)),'(?<=11+)0+(?=11+)','start','end');
L = cellfun(@(b,e)1+e-b,B,E,'uni',0)
L = 6×1 cell array
{[ 1]} {[ 1]} {0×0 double} {[ 1]} {[ 2]} {[ 3]}

カテゴリ

Help Center および File ExchangeLogical についてさらに検索

製品

Community Treasure Hunt

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

Start Hunting!

Translated by