0

I have a vector test2 that includes NaN 0 and 1 in random order (we cannot make any assumption).

test2 = [NaN 1 1 1 0 0 0 NaN NaN NaN 0 0 0 1 1 1 0 1 1 1 ];

I would like to group the elements containing consecutive 1 and to have in the separte vectors start and finish the first and last index of the groups.

In this case start and finish should be:

start = [2 14 18];
finish = [4 16 20];

I tried to adapt the code provided here coming up with this solution that is not working...could you help me with the right solution and tell me why the one I tried doesn't work?

a = (test2 ==1);
d = diff(a);
start = find([a(1) d]==1);                        % Start index of each group
finish = find([d - a(end)]==-1);                  % Last index of each group


start =

     2    14    18


finish =

     2     3     5     6     7     8     9    10    11    12    14    15    18    19

I am using MATLAB R2013b running on Windows. I tried also using MATLAB R2013a running on ubuntu.

Community
  • 1
  • 1
gabboshow
  • 5,359
  • 12
  • 48
  • 98

2 Answers2

3
a = (test2 ==1)
d=diff([0 a 0])
start=find(d==1)
finish=find(d==-1)-1

Padding a zero at the beginning and end is the easiest possibility. Then the special cases where a group starts at index 1 or ends at last index don't cause problems.

Full output:

>> test2 = [NaN 1 1 1 0 0 0 NaN NaN NaN 0 0 0 1 1 1 0 1 1 1 ]

test2 =

  Columns 1 through 16

   NaN     1     1     1     0     0     0   NaN   NaN   NaN     0     0     0     1     1     1

  Columns 17 through 20

     0     1     1     1

>> a = (test2 ==1)

a =

  Columns 1 through 16

     0     1     1     1     0     0     0     0     0     0     0     0     0     1     1     1

  Columns 17 through 20

     0     1     1     1

>> d=diff([0 a 0])

d =

  Columns 1 through 16

     0     1     0     0    -1     0     0     0     0     0     0     0     0     1     0     0

  Columns 17 through 21

    -1     1     0     0    -1

>> start=find(d==1)

start =

     2    14    18

>> finish=find(d==-1)-1

finish =

     4    16    20

>> 
Daniel
  • 36,610
  • 3
  • 36
  • 69
  • using the solution that you provided I get start = 3 15 19 and finish = 0 2 3 5 6 7 8 9 10 11 12 14 15 18 19 – gabboshow Jun 29 '15 at 17:50
  • @gabboshow: I added the full output of my command prompt, could you compare it with your output? No idea where the difference occurs. – Daniel Jun 29 '15 at 17:54
  • Thanks! it works! I think before I modified my solution...using your code (different from mine) I get the desired result... – gabboshow Jun 29 '15 at 17:59
2

The problem is the line finish = find([d - a(end)]==-1);, in particular that a(end) == 1. There are two steps to correcting this. First, change the problem line to finish = find(d==-1); This tells MATLAB, "Look for the elements where the difference between adjacent elements is -1". In other words, the vector shifts from 1 to 0 or NaN. If you run the code, you'll get

start =  2    14    18
finish = 4    16

Now, you'll notice the last element isn't detected (i.e. we should get finish(3) == 20. This is because the length of d is one less than the length of test2; the function diff cannot calculate the difference between the last element and the non-existant last+1 element!

To remedy this, we should modify a:

a = [(test2 == 1) 0];

And you will get the right output for start and finish.

Delyle
  • 529
  • 3
  • 14