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)
Show older comments
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]
0 Comments
Accepted Answer
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
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)]
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
Ahat(:,2:end-1) = Ahat(:,2:end-1).*Amask
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")
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)
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.
0 Comments
More Answers (1)
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);
0 Comments
See Also
Categories
Find more on Matrix Indexing in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!