MATLAB: Problem splitting large array into smaller arrays

arrayfor loopif statementloopMATLABsequential datasplitting array

I am trying to split my (n,5) array into smaller sections based on my 4th column. This column makes the data move in a sort of sine wave motion (peak to zero to valley to zero to peak…to zero to valley).
I am trying to split my data in the following manner: (where I want each color line to signify a new array)
(Plot:
plot(data(:,1),data(:,2)
)
For this, I am creating a loop that evaluates the conditions of column 4 and adds the data to a new array. As my first coding step I took the data and tried to separate them such that if the value on column 4 >= 0 then it would add them to a new array. So far I have:
new = [];
other = [];
pos = data(:,4);
x=1:1:5;
for ii = 1;
if (data(:,4)>=0)
new(ii) = [new,data(:,x)];
else
other(ii) = [other, data(:,x)];
end
end
However, doing this isn't working. It's just rewriting my original data set to a new variable. Is what I'm trying to do possible? Would it be better to do it without a loop (if possible)?
(I am trying to make this code as general as possible because the length of my sections (as seen in the image) will not always be the same.)
I attached a .txt file with my data, in case my explanation doesn't make sense.
Thank you in advance.

Best Answer

This works best with the findpeaks function:
D = load('data.txt');
x = D(:,1);
y = D(:,2);
[pksp,locpix] = findpeaks(y, 'MinPeakDist',50); % Find Positive ‘Points’ & Indices
x = x(locpix(1):end); % Redefine ‘x’
y = y(locpix(1):end); % Redefine ‘y’
locpix = locpix - locpix(1) + 1; % Redefine ‘locpix’
% locsp = x(locix-locix(1)+1); % Define ‘locsp’
[pksn,locnix] = findpeaks(-y, 'MinPeakDist',50); % Find Negative ‘Points’ & Indices
pksn = [-pksn; y(end)]; % Add End Index

locnix = [locnix; numel(x)]; % Add End Index
[pksz,loczix] = findpeaks(-abs(y), 'MinPeakDist',50); % Find Zeros ‘Points’ & Indices
[locs, idx] = sort([locpix; locnix; loczix]); % Sort ‘x’-Coordinates Indices
pks = [pksp; pksn; pksz];
pks = pks(idx); % Match ‘y’-Coordinates
for k1 = 1:numel(locs)-1
seg{k1} = [x(locs(k1):locs(k1+1)-1) y(locs(k1):locs(k1+1)-1)]; % Isolate ‘Segments’
end
figure(1)
plot(x, y); % Plot Data
hold on
for k1 = 1:size(seg,2)
plot(seg{k1}(:,1), seg{k1}(:,2), 'LineWidth',2) % Plot ‘Segments’
end
plot(x(locpix), pksp, '^r', 'MarkerFaceColor','r') % Optional


plot(x(locnix), pksn, 'vr', 'MarkerFaceColor','r') % Optional
plot(x(loczix), pksz, 'dr', 'MarkerFaceColor','r') % Optional
hold off
grid
Fortunately, your data have specific transitions, and the zero-crossings can also be made into specific transitions, so findpeaks is perfect for this. My code segments the data, and the plot demonstrates that your curve appears to be segmented correctly.
I did not categorise the segments in my code into ‘positive-falling’, ‘negative-falling’, ‘negative-rising’, etc., so I leave that to you. That involves your writing another loop to segment the ‘segs’ cell array the way you want. That should be relatively straightforward. I did my best to comment-document my code.
There is unfortunately no easy way to vectorise this. I cannot claim that it will be robust to all your data unless they are similar to those you posted. You may have to generalise it yourself for other data.
Experiment to get the result you want.
NOTE The colors on the plot do not correspond to those in your Question. They simply demonstrate that the segmentation works.
EDIT Corrected typographical errors, added optional ‘positive peak’, ‘negative peak’, and ‘zero crossing’ markers to plot (not shown in posted plot).