How to count the number of consecutive negative values in a vector?

9 views (last 30 days)
Hello! What is the most time-saving method (using the vectorization style or others but not for loops) to count the maximum number of consecutive negative values in a vector?
The problem is that there are thousands of vectors of the same length and if one contains more than 3 consecutive negative values then it will be removed from the data set. For example, vector v1 will be deleted due to [-1 -1 -3] chain, but v2 will remain:
v1 = [11 2 3 -1 -2 1 -1 -1 -3 1 3 1]
v2 = [3 -1 4 1 33 44 -11 -3 4 11 3 -1]
Can it be get done by using array modifying functions only (like 'repmat', 'diff', 'cumsum' etc. not consuming ones like 'find')?
Many Thanks!
  2 Comments
Stephen23
Stephen23 on 12 Jan 2018
Edited: Stephen23 on 12 Jan 2018
"The problem is that there are thousands of vectors..."
That is indeed a major problem of your code design.
Once you put all of your data into lots of separate variables like that then you force yourself to write slow, buggy, complex, obfuscated code when you try to access them. Trying to magically access thousands or variable names is what beginners do because they don't realize that they are making their code and data much slower and buggier.
The simpler, neater, and much more efficient way of accessing data is to use indexing.
The two main ways that beginners end up with thousands of numbered variables in their workspace (magically defining them, or using load) can both be trivially altered to use just one array with indexing, so your best option is to change your code design. Read this to know more:
V. Luong
V. Luong on 12 Jan 2018
Yes, the data set is loaded only once into a massive array and the variables v1 v2 are just for clearer explanation. Thank you for your comment!

Sign in to comment.

Accepted Answer

Jonathan Chin
Jonathan Chin on 11 Jan 2018
Edited: Jonathan Chin on 11 Jan 2018
This might work using cumsum to find all the negatives in a group and hist to count the consecutive negatives
v1 = [11 2 3 -1 -2 1 -1 -1 -3 -1 1 3 1];
v2 = [3 -1 4 1 33 44 -11 -3 4 11 3 -1];
x = [0 cumsum(v1>=0)]; %makes all the values positive increment the sum, so all negative numbers will keep the next number the same
numNeg=max(hist(x)-1); % find number of consecutive negative by looking counting all the similar numbers and subtracting 1 for the initial increment

More Answers (2)

Image Analyst
Image Analyst on 11 Jan 2018
I don't see how any of the other answers are getting rid of the vector. You'd need to use the clear function for that. You can use regionprops(), in the Image Processing Toolbox to get the lengths of all the negative runs of values, then clear to get rid of the vector. So try this with your vectors.
% Find lengths of negative values.
props = regionprops(vec < 0, 'Area');
% If 3 negatives in a row or longer, clear vector - get rid of it completely.
if max([props.Area]) >= 3
clear vec;
end
I call it vec, but you'd call the code using v1, v2, v3, v4, ...... v9000. You could put it into a function like
function deleteIt= ClearIf3Negatives(vec)
deleteIt = false;
% Find lengths of negative values.
props = regionprops(vec < 0, 'Area');
% If 3 negatives in a row or longer, clear vector - get rid of it completely.
if max([props.Area]) >= 3
deleteIt = true;
end
Then call it like
if ClearIf3Negatives(v1), clear(v1), end;
if ClearIf3Negatives(v2), clear(v2), end;
...
if ClearIf3Negatives(v9000), clear(v9000), end;
But PLEASE tell me you don't actually have thousands of separately named vectors like you said. That would be such bad programming practice.
  1 Comment
V. Luong
V. Luong on 12 Jan 2018
Thank you very much! Never have I used any functions in Image Processing Toolbox. I will try and see if your solution is faster than Jonathan's.

Sign in to comment.


Birdman
Birdman on 11 Jan 2018
Edited: Birdman on 12 Jan 2018
Download the file from the link and use rcumsum function.
idx=find(rcumsum(v1<0)==3);
v1([idx-2:1:idx])=[];
(EDITED)
I understood that those consecutive negative values should be deleted from the array, therefore my answer looks like this. To delete v1, just type
idx=find(rcumsum(v1<0)==3);
if ~isempty(idx)
clear v1;
else
end
  2 Comments
V. Luong
V. Luong on 12 Jan 2018
Edited: V. Luong on 12 Jan 2018
Many thanks to you! I just saved your function 'rcumsum' for upcoming projects. As we are currently working as a team of dozens of members and our highest priority is stability so we have to use built-in functions only
Image Analyst
Image Analyst on 12 Jan 2018
regionprops(), max(), and clear() (used in my solution) are built in functions. rcumsum() is not a built-in function - it's a user-submitted function, though it's built upon built in functions.
I also question why you need to clear the vector. I virtually never clear variables except if I'm using to many large image arrays that I need to because otherwise the user would run out of RAM memory. Normally, I just let the garbage collector free up the space automatically when the function returns. Why do you think you need to call clear?

Sign in to comment.

Categories

Find more on Matrices and Arrays in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!