Problem splitting large array into smaller arrays

3 views (last 30 days)
yz on 20 Dec 2017
Commented: Star Strider on 3 Jan 2018
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 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)
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);
for ii = 1;
if (data(:,4)>=0)
new(ii) = [new,data(:,x)];
other(ii) = [other, data(:,x)];
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.

Accepted Answer

Star Strider
Star Strider on 20 Dec 2017
Edited: Star Strider on 20 Dec 2017
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’
plot(x, y); % Plot Data
hold on
for k1 = 1:size(seg,2)
plot(seg{k1}(:,1), seg{k1}(:,2), 'LineWidth',2) % Plot ‘Segments’
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
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).

More Answers (0)

Community Treasure Hunt

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

Start Hunting!