Extract data between thresholds

3 views (last 30 days)
Gaëlle Broca
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.
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.
Thank you in advance !

Accepted Answer

KSSV on 9 Apr 2021
Edited: KSSV on 9 Apr 2021
A = load('test.txt') ;
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'});
You got all the four arrays in out.
  1 Comment
Gaëlle Broca
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.

Sign in to comment.

More Answers (1)

Julius Muschaweck
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
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 ');
if length(startidx) ~= length(stopidx)
error(' must have same number of starts and stops ');
% 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;
% plot the four individual ranges
% note that the zero values are missing, just like they should.
hold on;
for i = 1:length(my_arrays)
t = my_arrays{i};
plot(t.x, t.y);
axis([x(1) x(end) -0.1 1.1]);
  1 Comment
Gaëlle Broca
Gaëlle Broca on 9 Apr 2021
A very different take than previous answer, I'll look into it deeper, thank you

Sign in to comment.


Find more on Multidimensional Arrays 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!

Translated by