Reputation: 1
I'm trying to create some code that will do something like this: In the time series when v crossed zero from negative to positive, this was separated by at least 4 days from other zero crossings (left and right direction), and if I take 8 elements (from zero crossings) to the right, at least the 80% of the days were positive, and if I take 6 elements to the left (from zero crossings), at least the 60% of the days were negative. the series that meets these conditions are bookmarked or saved with the position.
Thanks for your help..
v=[-1 2 3 -9 -8 -6 -7 -9 -3 -2 -5 -6 -3 1 6 8 5 9 7 4 5 6 -5 -7 2 5 3 2 -2 -1 -5 -4 1 4 3 5 6 3 4 3 -4 5]
With this program I can extract the position when the value change from positive to negative or vice versa.
vexample=v;
vexample(vexample >= 0) = 1;
vexample(vexample < 0) = -1;
z = vexample > 0;
id = find([true;diff(vexample.') ~= 0]);
k = diff([id;numel(vexample)+1]);
out = -k;
out(z(id)) = k(z(id));
clear id k vexample z
out = -1 2 -10 9 -2 4 -4 8 -1 1
And now, I'm trying to detect the part of the series that meets the conditions, but I've got problems with that
Upvotes: 0
Views: 236
Reputation: 12345
This is pretty confusing. I actually find that it is often best to step back and redefine exactly what I need in code/math, rather than words. For example, instead of
8 elements (from zero crossings) to the right, at least the 80% of the days were positive
Try
%Find all N such that
sum(sign(v((N):(N+7)))) >= ceil(0.60 * 8)
That naturally begs a few questions, such as (N+7)
or (N+8)
.
I've made a simple attempt at doing this for your paragraph of requirements:
%Given the input
v=[-1 2 3 -9 -8 -6 -7 -9 -3 -2 -5 -6 -3 1 6 8 5 9 7 4 5 6 -5 -7 2 5 3 2 -2 -1 -5 -4 1 4 3 5 6 3 4 3 -4 5];
%Find all N such that
% **** low to high zero crossing
% (1) v(N) > 0
% (2) v(N-1) < 0
% **** +/- 4 days of no zero crossings
% (3) all(v((N-5):(N-1)) < 0)
% (4) all(v((N):(N+4)) > 0)
% **** +/- 8 days of rare zeros crossings
% (3) sum(sign(v((N-8):(N-1)))) <= - floor(0.60 * 8)
% (4) sum(sign(v( (N):(N+7)))) >= ceil(0.80 * 8)
At this point (and once you agree with my translations) than it's pretty easy to write the appropriate loop:
%Simple loop
maskResult = false(size(v));
vSign = sign(v);
for ix = 9:(length(v)-8)
if ...
all(vSign((ix-5):(ix-1)) < 0) && ...
all(vSign((ix):(ix+4)) > 0) && ...
sum(sign(vSign((ix-8):(ix-1)))) <= - floor(0.60 * 8) && ...
sum(sign(vSign( (ix):(ix+7)))) >= ceil(0.80 * 8)
maskResult(ix) = true;
end
end
And you can check the results using
find(maskResult) %returns 14, indicating the -3 -> 1 transition
Upvotes: 0
Reputation: 3461
To be honest, I think you are confusing yourself and the readers of this question way more than you need to. It looks like you are proficient in MATLAB from your above code so my answer to you is to just break it down in parts.
First find all indices of zero crossings (I think that's what id is?)
Now you can make it kinda simple and eliminate indices that are within 4 of each other. Use a for loop and if statements to make a vector of invalid (closer within 4). After your for loop passes through, delete those.
To be honest, I am not clear what you are even trying to do in this part:
if I take 8 elements (from zero crossings)to the right, at least the 80% of the days were positive, and if i take 6 elements to the left (from zero crossings), at least the 60% of the days were negative.
But that should be easy enough with some basic if statements..
All cool programming projects were done in baby steps and that's how I suggest you start as well.
Upvotes: 2