How to count how often a variable returns to zero and then increases from zero

Hi everyone, imagine you have a table of Time and a Y variable, could be anything, current, voltage, torque etc. What would be the best way to code MATLAB to count how often the value goes down to zero and then increases above zero again? E.g.
Time Voltage
_____ _____
1 3
2 2
3 1
4 0
5 1
6 0
7 2
8 3
9 0
10 3
11 3
12 2
13 1
14 0
15 1
16 0
17 2
18 3
19 0
So you can see sometimes the voltage starts to rise, and then it drops, and eventually hits 0, and then starts to rise, and then starts to fall, and then hits zero etc.I want some kind of counter that would increase every time the value drops to zero (or some threshold) and then increases above the threshold again.

4 Comments

It would be helpful if you supply a piece of data as it is really. Maybe some code what you have done allready. And what is your threshold?
The threshold is pretty arbirtary though, and so is the data itself. It can really be anything. Its a table, and the first column is time. The second column is the Y variable. Sometimes the Y variable drops to zero for a fixed period of time and then increases again. And I just want a counter that increase every time it does that. It is possible for the Y variable to slightly bump up above 0 by a fraction and then drop to zero again, hence the need for a threshold. But it could be 1 or 2 or 3. The sample data I provided is a pretty good representation. Only thing is the actual data has decimal points, there are millions of samples, and it can remain at zero for many samples in a row. Its a bit tricky to share the data as it's sensitive to share in a public space. So that is why I have made up some sample data to give an idea. I would guess a lot of people working with MATLAB would have similar issues regarding actually uploading the data they are working on.
OK. Just for my understanding: What should be the outcome of your (19) lines you have shown above?
And another question: What do you mean with "pretty arbitraty"? I think you can't work with a threshold you have no idea about it.

Sign in to comment.

Answers (2)

It appears this parameter never goes negative.
Are your sets ALWAYS such that a zero is always alone? So when it hits zero, it never stays there?
If this is true, then just count the number of zeros. If a zero as the very first or last element does not count, then subtract 1 if the first element is a zero. Subtract 1 if the last element is a zero.
It seems trivial. If there are cases where the variable stays at zero, then just subtract 1 from the count whenever a zero is followed by another zero.
Again, all of this is trivial. As far as being in a table, just extract that variable from the table. Tables are not the only variable type in MATLAB, and tables often make your work far more difficult. So for the computation, just extract that variable as a vector. LEARN TO USE MATLAB. If all you ever do is use tables, you are just using MATLAB as a pseudo-spreadsheet. For example:
V = randi([0,3],[1,20])
V = 1x20
0 2 1 3 0 2 0 1 0 0 0 3 0 3 3 0 3 1 0 1
Zcount = sum(V == 0) % how many zeros?
Zcount = 9
Zcount = Zcount - (V(1) == 0) - (V(end) == 0) % Discard a zero at an end
Zcount = 8
Next, we need to discard multiple consecutive zeros in that count, But I assume that a sequence like [1 0 0 1] still counts as one event when it hit zero. How can we do that? Just search for any pairs of consecutive zeros.
Zcount = Zcount - numel(strfind(V,[0 0]))
Zcount = 6
So if we had a string like [1 0 0 0 1], we would find TWO consecutive pairs of zeros, but still one event. In fact, in the random string you see above, there was an initial zero. I discarded that from the count. Then there was a tripleton zero, so I cut the count by 2. In the end, there were exactly 6 events of the class you want to see.
I think this is what you want to see, but you should understand from my explanations if some of those tests are not what you wanted.
When you don't know how to solve a problem, start by finding something that might get you close to a solution. Can you then modify that? Make it better? Get you closer to a solution. Many problems in MATLAB can be resolved this way.

2 Comments

Yes the parameter never drops below zero. But it can remain at zero for multiple data points in a row. I just didn't do that in the example. The counter would need to not increase unless the variable rose above a threshold and then dropped below it again
The data also contains millions of data points. You can't just count the zeros.
And you can have decimel points. So the data could go 0 0 0 0 0 0.1 0 0 5 and you would only count 1
It may seem trivial to you but I am struggling with this :-D
"The data also contains millions of data points. You can't just count the zeros."
Sure you can.
% a vector of a billion elements, each of which is zero or one:
v = randi([0,1],1e9,1);
% count the zeros and time how long it takes to do so:
t = tic();
n_zeros = nnz(v == 0);
dt = toc(t);
% display the number of zeros and the time it took to count them:
disp(sprintf('It took %g seconds to count %d zeros.',dt,n_zeros))
It took 1.14198 seconds to count 499966702 zeros.
Did you try the answer?

Sign in to comment.

One method to find the first instance of a zero value is to use the strfind function. You can use it again to determine the indices of a return from a zero value, then use those results to determine the start and end indices of the non-zero values. If you want the non-zero values themselves, use accumarray to retrieve them, then if necessary, edit the results —
A = [ 1 3
2 2
3 1
4 0
5 1
6 0
7 2
8 3
9 0
10 0
11 0
12 3
13 3
14 2
15 1
16 0
17 1
18 0
19 2
20 3
21 0];
TV = array2table(A, 'VariableNames',{'Time','Voltage'})
TV = 21×2 table
Time Voltage ____ _______ 1 3 2 2 3 1 4 0 5 1 6 0 7 2 8 3 9 0 10 0 11 0 12 3 13 3 14 2 15 1 16 0
Vv = TV.Voltage ~= 0
Vv = 21×1 logical array
1 1 1 0 1 0 1 1 0 0 0 1 1 1 1 0 1 0 1 1 0
zero_start = strfind(Vv.', [1 0])+1
zero_start = 1×6
4 6 9 16 18 21
zero_end = strfind(Vv.', [0 1])
zero_end = 1×5
4 6 11 16 18
nz = cumsum(TV.Voltage == 0) + 1;
TVNZ = accumarray(nz, (1:numel(nz)).', [], @(x){TV(x(TV{x,2}~=0),:)})
TVNZ = 9×1 cell array
{3×2 table} {1×2 table} {2×2 table} {0×2 table} {0×2 table} {4×2 table} {1×2 table} {2×2 table} {0×2 table}
Lv = cellfun(@(x)~isempty(x),TVNZ);
Result = TVNZ(Lv);
Result{:}
ans = 3×2 table
Time Voltage ____ _______ 1 3 2 2 3 1
ans = 1×2 table
Time Voltage ____ _______ 5 1
ans = 2×2 table
Time Voltage ____ _______ 7 2 8 3
ans = 4×2 table
Time Voltage ____ _______ 12 3 13 3 14 2 15 1
ans = 1×2 table
Time Voltage ____ _______ 17 1
ans = 2×2 table
Time Voltage ____ _______ 19 2 20 3
I’m not certain what result you want, however one of these should provide an approach to it.
.

Categories

Asked:

on 21 Feb 2024

Commented:

on 22 Feb 2024

Community Treasure Hunt

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

Start Hunting!