3

I have a vector of 1s and 0s that represent when an intermittent data signal is occurring. E.g.:

    V = [0,0,0,0,1,1,1,1,1,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0];

How do I find the index value of every change from 1 to 0? So for vector V above, the answer would be:

    idx = [10,18,28];
humbleHacker
  • 437
  • 6
  • 17

6 Answers6

7

Quick and easy:

idx=find(diff(V)<0)+1;

Compute the derivative, get only the negative values (from 1 to 0 is -1) and find the locations. As the derivatives start from the second location, we need to add 1

However, note that if what you want is accessing data on those locations, it's better to use the logical indices directly, as in:

somevals=my_other_data([false;diff(V)<0]);

Read more about general variable indexing here

Ander Biguri
  • 35,140
  • 11
  • 74
  • 120
6

strfind is more than just strings and also suitable for situations like yours.

idx = strfind(V,[1 0]) + 1;
Sardar Usama
  • 19,536
  • 9
  • 36
  • 58
2

You can also use a convolution:

idx = find(conv(V,[-1,1])==1);
obchardon
  • 10,614
  • 1
  • 17
  • 33
1

If you want a generic solution which works for "index of every time the value changes from x to y", use this vectorised approach:

idx = find( ( V(1:end-1) == x ) & V(2:end) == y ) ) + 1;

In your case

idx = find( ( V(1:end-1) == 1 ) & ( V(2:end) == 0 ) ) + 1;
% >> idx = [10 18 28]

As with Ander's solution, if you're using this for indexing then find is an unnecessary slow-down, just use this

idx = [false, ( V(1:end-1) == 1 ) & ( V(2:end) == 0 )];
Wolfie
  • 27,562
  • 7
  • 28
  • 55
1

You can use find to locate 0's and 1's and use intersect to find edges, in general

>> intersect(find(V==0), find(V==1)+1)
ans =
    10    18    28

You can replace 0 and 1 with any arbitrary value. But if you are dealing with only 0's and 1's you can simplify it to

>> intersect(find(~V), find(V)+1)
ans =
    10    18    28
Mohsen Nosratinia
  • 9,844
  • 1
  • 27
  • 52
0

One way would be to write a loop. It's been a while since I've used matlab so forgive me if my syntax is a bit off, but something with similar logic to this should work:

Given your vector V:

idx = [];
for i = 1:(length(V) - 1)
  if (V(i) == 0 && V(i+1) == 1)
    idx = [idx, (i + 1)];
  end
end

Good luck! Let me know if it doesn't work for some reason. If you're going to be performing this actions a lot, you should probably write a function too.

Stephen
  • 399
  • 3
  • 8
  • 1
    This works, but definitely very far from the easiest way in MATLAB. This is good for C – Ander Biguri Aug 08 '18 at 10:45
  • This exact logic [can be vectorised](https://stackoverflow.com/a/51745032/3978545), make the most of the native MATLAB functionality! – Wolfie Aug 08 '18 at 11:02