I have a matrix given below. I want to count the number of sets of consecutive non zero values along each row. Detailed description and desired result given below

9 views (last 30 days)
A = [0 0 3 4 1 0 7 8;
6 0 0 4 5 1 0 0]
In the first row there are 2 sets of consecutive non zero values i.e. First set of nonzero consecutive is (3 4 1) and second set of non zero consecutive values is (7 8). In the second row there is only one set of non zero consecutive values, that is (4 5 1).
desired_set_of_non_zero_consecutive_values=[2;1]

Accepted Answer

John D'Errico
John D'Errico on 1 Jul 2023
Edited: John D'Errico on 1 Jul 2023
These problems are always simpler, IF you reduce it to simpler sub-tasks. And, I'm sure there are simpler ways to solve this problem. But what I'm doing in this answer is to show you how you might think through a problem, not so much find the very simplest scheme to solve the problem. Arguably, that would just involve a loop.
You need to remember your target, and then find ways to get closer and closer to that goal.
It looks like singleton elements that are not consecutive non-zeros don't count. And I'll add a few rows to make it interesting, making sure we can resolve all issues.
A = [0 0 3 4 1 0 7 8;
6 0 0 4 5 1 0 0;
1 2 3 0 1 2 0 1;
0 0 0 1 2 3 4 0;
0 0 0 0 1 0 0 0;
0 0 0 0 0 0 0 0];
First, turn this into a boolean matrix. All we care about are the non-zeros.
Ahat = A ~= 0
Ahat = 6×8 logical array
0 0 1 1 1 0 1 1 1 0 0 1 1 1 0 0 1 1 1 0 1 1 0 1 0 0 0 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
Next, I'll pad a spare zero at the beginning and the end of each row. This will make it easier to find the strings of non-zeros, and also to kill off those pesky singletons.
nr = size(A,1);
Ahat = [false(nr,1),Ahat,false(nr,1)]
Ahat = 6×10 logical array
0 0 0 1 1 1 0 1 1 0 0 1 0 0 1 1 1 0 0 0 0 1 1 1 0 1 1 0 1 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Next, we want to kill off those singleton elements in any row. Surely many ways to do this. But I'll pick a simple one.
Amask = conv2(Ahat,[1 2 4],'valid') ~= 2
Amask = 6×8 logical array
1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
Ahat(:,2:end-1) = Ahat(:,2:end-1).*Amask
Ahat = 6×10 logical array
0 0 0 1 1 1 0 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 1 1 0 1 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
So EVERY consecutive block of non-zeros is in there, but only the ones longer than 1 element. And every one of those blocks ends with the sub-string [1 0]. So all we need to do now is count the number of times we find the sub-string [1 0] in each row. Again, break larger problems down into simpler ones.
loc = strfind(string(char(Ahat + '0')),"10")
loc = 6×1 cell array
{[ 6 9]} {[ 7]} {[ 4 7]} {[ 8]} {0×0 double} {0×0 double}
That line looks to be a kludge, but it works, and I'm not going to spend any mental energy to make it shorter. Nice though. It gives me a cell array containing the locations of the end points of all consecutive sub-strings. All we need to do now is to count the number of elements in each entry of that cell array.
desired_set_of_non_zero_consecutive_values = cellfun(@numel,loc)
desired_set_of_non_zero_consecutive_values = 6×1
2 1 2 1 0 0
It actually is not that large a set of steps I went through, though I think, since I left off the semi-colons, and spent a lot of time talking through the problem, it probably seems a lengthy solution. But the point is to teach how to tackle a problem like this.
Break big problems down into small ones. Eat programming elephants one byte at a time.

More Answers (1)

sp6038sy
sp6038sy on 1 Jul 2023
Edited: sp6038sy on 1 Jul 2023
Another approach —
I tried to find the number of continuous data by finding the start and end points of the continuous data.
A = [0 0 3 4 1 0 7 8;
6 0 0 4 5 1 0 0];
desired_set_of_non_zero_consecutive_values = zeros(height(A), 1);
padA = padarray(A, [0,1]);
binMap = padA ~= 0;
for i = 1:height(padA)
len = find(-1 == diff(binMap(i, :))) - find(1 == diff(binMap(i, :)));
desired_set_of_non_zero_consecutive_values(i) = sum(len >= 2);
end
disp(desired_set_of_non_zero_consecutive_values);
2 1

Products

Community Treasure Hunt

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

Start Hunting!