UpperEastSide
UpperEastSide

Reputation: 137

MATLAB: Identify maxima and minima and split data accordingly

I have the following arrays:

x = [1:33]; 
y = [0 1 2 3 4 5 4 3 2 1 0 1 2 3 4 5 4 3 2 1 0 1 2 1 0 1 2 3 4 3 2 1 0];

I need to separate y into different sections. I need to obtain the ascending parts, the descending parts, and the combined ascending and descending parts.

For example:

 Ascending parts = [1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 0 0 1
 1 1 1 0 0 0 0]; 

 Descending parts = [0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1
 1 1 1 1 0 0  1 1 0 0 0 0 1 1 1 1]; 

 Combined parts = [1 1 1 1 1 1 1 1 1
 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 4 4 4 4 4 4 4 4];

I can, of course, do this manually for these arrays, but I need to do this for arrays with hundreds of thousands of points and I wish to do it automatically. I have been playing around with the findpeaks functions but this isn't straightforward as it sometimes picks up peaks during the descending/ascending parts, rather than at the end points.

Any tips on how I can do this?

version MATLAB 2017/b

Upvotes: 1

Views: 55

Answers (1)

jrook
jrook

Reputation: 3519

For a problem like this, you should consider using Matlab's diff.

For y = [0 1 2 3 4 5 4 3 2 1 0 1 2 3 4 5 4 3 2 1 0 1 2 1 0 1 2 3 4 3 2 1 0];

a=diff(y)
1   1   1   1   1   -1  -1  -1  -1  -1  1   1   1   1   1   -1  -1  -1  -1  -1  1   1   -1  -1  1   1   1   1   -1  -1  -1  -1

b=a, c =a;
b(b<0)=0;
c(c>0)=0;

Will give you:

b = 1   1   1   1   1   0   0   0   0   0   1   1   1   1   1   0   0   0   0   0   1   1   0   0   1   1   1   1   0   0   0   0

c = 0   0   0   0   0   -1  -1  -1  -1  -1  0   0   0   0   0   -1  -1  -1  -1  -1  0   0   -1  -1  0   0   0   0   -1  -1  -1  -1

For the second part, you can do the following:

z=diff(y, 2);
zd=[0 find(z~=0);0 z(find(z~=0))]

0     5    10    15    20    22    24    28    32
0    -2     2    -2     2    -2     2    -2     2

Assuming that this is how your function looks like in general, the above pattern shows convex and concave regions in the sequence. With this assumption, the following should work in your case:

za=[0 zd(1,zd(2,:)>0)];
zad=diff(za);
cell2mat(arrayfun(@(x,y) repelem(x,y), 1:length(zad),zad,'UniformOutput',false))

ans: 1  1   1   1   1   1   1   1   1   1   2   2   2   2   2   2   2   2   2   2   3   3   3   3   4   4   4   4   4   4   4   4

which I believe is close to what you want. Hope this helps.

Upvotes: 1

Related Questions