Identifying change of sign of a data and make a group for every 2 changes of sign.

1 view (last 30 days)
Hi, Well as my question says, i need help to make groups of data for every 2 changes of sign, for example i have this data:
0.1 -0.16966
0.2 -0.072523
0.3 0.21066
0.4 -0.06312
0.5 -0.14626
0.6 0.14327
0.7 0.010853
And i want a code that make me this following groups:
Group 1: -0.16966, -0.072523, 0.21066
Group 2: -0.06312, -0.14626, 0.14327, 0.010853
And then, find the max and min for each group, add them, find the average of all group:
G=matrix with all the groups
a=max(G)
b=min(G)
A=mean(a+abs(b))
I have done a code which makes this but in order to work i need to put Zeros value in between of a change of sign and i have like 300 points so it takes time,
the code that i have right now is:
clear all
close all
%--------------------------OPTIMIZATION OF TMD----------------------------%
%Load files%
for u = 0:20:220;
C= strcat('TMD_',num2str(u),'.csv');
load(C);
end
%------C=0 N*s/m------%
c0=0;
t0=TMD_0(:,2); %seconds%
vy0=TMD_0(:,3); %m/s%
allzeros = find(vy0 == 0);
x0 = allzeros(1:2:end);
z0 = zeros(length(x0),1);
a0 = zeros(length(x0),1);
for i=1:length(x0)-1
y0 = vy0(x0(i):1:x0(i+1));
z0(i) = max(y0);
a0(i) = min(y0);
end
yend0 = vy0(x0(end-1):1:x0(end));
z0(length(x0)) = max(yend0);
a(length(x0)) = min(yend0);
B0 = z0+abs(a0);
A0 = mean(B0);
Thanks for the ideas!

Accepted Answer

Guillaume
Guillaume on 9 Sep 2014
%generate some data for demo purpose:
x = 0:3*360;
data = x.*(sind(x)+cosd(2*x));
plot(data);
datasign = sign(data); %get the sign of the data.
%find where it goes from -1 to 1 or 1 to -1. Problem is there may be some 0 in between
%so first remove the zero, but remember where everything was:
[~, oldindices, nozerosign] = find(datasign);
%now find the transitions in nozerosign. It's where the diff is non-null
zerocross = find(diff(nozerosign));
%transform the indices in nozerosign into indices in data
zerocross = oldindices(zerocross)+1;
%we now know where every zero crossing occurs, split the data accordingly
splitboundaries = [1 zerocross(2:2:end) numel(data)];
splitcount = numel(splitboundaries)-1;
localmins = zeros(1, splitcount);
localmaxs = zeros(1, splitcount);
for splitidx = 1:splitcount
splitdata = data(splitboundaries(splitidx):splitboundaries(splitidx+1));
localmins(splitidx) = min(splitdata);
localmaxs(splitidx) = max(splitdata);
end
  3 Comments
Guillaume
Guillaume on 10 Sep 2014
Edited: Guillaume on 10 Sep 2014
The reason you're getting the error is simply that your data is a column vector whereas my example uses a row vector. Transposing one of data, datasign or zerocross or doing a vertical concatenation would solve the problem.
The algorithm I wrote can be divided in two parts, the first part finds where the data crosses zero. That's when its sign goes from -1 to 1 or vice-versa, so that's what it's finding. A slight complication is that there may be some 0s (when the data is 0) in between the -1 to 1 and that's what most of the lines deal with.
I've just now realised that it would be much simpler to just remove the 0s in the first place since you don't care about them anyway. The first part of the algorithm would just be:
%demo data:
x = 0:3*360;
vy20= transpose(x.*(sind(x)+cosd(2*x))); %column vector just as yours
plot(data);
vy20(vy20 == 0) = []; %remove the zeros
zerocross = find(diff(sign(vy20))); %much simpler!
The values in zerocross are thus the indices of the points just before the data crosses the x-axis (and zerocross+1 are the indices of the points just after).
The 2nd part of the algorithm just batches the data every 2nd zerocross. The 1st batch goes from index 1 to zerocross(2), the 2nd from zerocross(2) to zerocross(4), etc, the last from zerocross(end) to the end of the data (which is numel(vy20)). This may be easier to understand:
startindices = [1; zerocross(2:2:end)] %vertical concatenation as zerocross is column
endindices = [zerocross(2:2:end)+1; numel(vy20)] %same
localmins = zeros(1, numel(startindices)); %preallocate
localmaxs = zeros(1, numel(startindices)); %preallocate
for splitidx = 1:numel(startindices)
splitdata = vy20(startindices(idx):endindices(idx));
localmin(splitidx) = min(splitdata);
localmax(splitidx) = max(splitdata);
end
I've not really focussed on that 2nd part, there may be some way to do it without a for loop.
Max
Max on 10 Sep 2014
Thank you very much! it works perfectly! now, i don't have to worry to write zeros in between for my code! i really appreciate your help! thank you!

Sign in to comment.

More Answers (0)

Categories

Find more on General Physics 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!