# Extract data between thresholds

2 views (last 30 days)
Gaëlle Broca on 9 Apr 2021
Commented: Gaëlle Broca on 9 Apr 2021
Hi everyone,
I'm encountering a problem with my data analysis and hope to find some solution. I already gave a look at other threads to see if anyone had the same problem and resolved it, but no one aimed to do what I intend to.
In short, I have these data in csv (or txt) format that can be graphically represented here : I would like to index these data into 4 different arrays, one for each period.
With
[row]=find(filename==0)
I can identify where the 0s are and then manually index the data, but as I have a lot of files I would like to automate it. I could put thresholds but I have 2 criteria for them :
For stop threshold :
• value contained in cell 1 > cell2
• cell 2 = 0
For start threshold :
• value contained in cell 1 < cell 2
• cell 1 = 0
As you can see, thresholds can't be a fixed value, and I have more than one period to identify, hence I'm having difficulty. I'm far from a Matlab expert so maybe I'm missing something easy, in that case I would gladly appreciate your help.
##### 2 CommentsShowHide 1 older comment
Gaëlle Broca on 9 Apr 2021
Here's the data used

KSSV on 9 Apr 2021
Edited: KSSV on 9 Apr 2021
A = A' ;
ii = zeros(size(A));
jj = A > 0;
ii(strfind([0,jj(:)'],[0 1])) = 1;
idx = cumsum(ii).*jj;
out = accumarray( idx(jj)',A(jj)',[],@(x){x'});
celldisp(out)
You got all the four arrays in out.
Gaëlle Broca on 9 Apr 2021
Thank you, it was definitely what I needed, and definitely not close to what i found beforehand so I'm glad I asked.

Julius Muschaweck on 9 Apr 2021
I believe logical indexing and the diff function are what you need.
% create and plot something like your data
x = 0:300; % some x value
y = - cos(x * 8 * pi / 300); % about 4 full cosine cycles, the minus sign makes it start at -1
y ( y<0 ) = 0; % use logical indexing to set negative values to zero
figure(); % looks somewhat like your data
plot(x,y);
axis([-Inf Inf -0.1 Inf]); % make sure the y=0 lines are visible
% manual inspection of y reveals that you want index ranges 20:57, 95:132 etc
dy = diff(y); % difference between adjacent elements -- the first part of your conditions
% extend dy to enable logical operation on same size arrays
dystart = [dy,0]; % dystart(i) is y(i+1) - y(i) -- your start condition
dystop = [0,dy]; % dystop(i) is y(i) - y(i-1) -- your start condition
justbeforestart = (y == 0) & (dystart > 0); % your start condition
justafterstop = (y == 0) & (dystop < 0); % your stop condition
% both just... arrays have same length as x, mostly 0, only 1 where condition is detected
% extract the start and stop indices
idx = 1:length(x); % the array of indices
% use logical indexing again to extract start/stop indices
startidx = idx(justbeforestart) + 1; % add 1 to get actual "start" from "justbeforestart"
stopidx = idx(justafterstop) - 1; % subtract 1 to get "stop"
% sanity checks
if y(1) ~= 0 || y(end) ~= 0
error(' data must start and end with zero ');
end
if length(startidx) ~= length(stopidx)
error(' must have same number of starts and stops ');
end
% extract the four data ranges and put them into a cell array
my_arrays = {};
for i = 1:length(startidx)
% create a struct with fields x and y for each data range
s.x = x(startidx(i) : stopidx(i) );
s.y = y(startidx(i) : stopidx(i) );
my_arrays{i} = s;
end
% plot the four individual ranges
% note that the zero values are missing, just like they should.
figure();
hold on;
for i = 1:length(my_arrays)
t = my_arrays{i};
plot(t.x, t.y);
end
axis([x(1) x(end) -0.1 1.1]);  Gaëlle Broca on 9 Apr 2021
A very different take than previous answer, I'll look into it deeper, thank you

R2020b

### Community Treasure Hunt

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

Start Hunting!