Patrik Westerberg
Patrik Westerberg

Reputation: 13

Interplay of values between two vectors in Matlab

I have two vectors o and c of equal length:

o = [-1 -1 -1  0 0 0 1 1 0  0];
c = [-1 -1 -1 -1 0 1 1 1 0 -1];

o represents opening signals (neg or pos) and c represents closing signals, assuming an opening signal has preceeded it with opposite sign. Only one signal can be active at a time so consecuitive signals must be ignored. In the two vectors above, my first signal would be in o(1) and its corresponding closing signal would be found in c(6). This also means that the opening signals in o(2) and o(3) should be ignored and my next opening signal is found at o(7) with its corresponding close at c(10), consequently leading to a void signal at o(8)

I am trying to find a vectorized solution to identifying a correct sequence or indices of opened/closed signals to produce something along the lines of the following solution example:

o = [-1 0 0 0 0 0 1 0 0  0];
c = [ 0 0 0 0 0 1 0 0 0 -1];

I can obviously solve this by looping through each element in a for loop but since my dataset can be up to millions of elements and I find looping in Matlab can be rather 'expensive', I would greatly appreciate if someone has a solution to my problem that is more matrix-oriented, or through arrayfun or something equivalent that may make the code more efficient?

Upvotes: 1

Views: 711

Answers (2)

abcd
abcd

Reputation: 42235

You can use diff, along with some logical operations to get your answer.

o=[-1,-1,-1,0,0,0,1,1,0,0];
oFinal=abs(diff([0,o])).*o;

oFinal=

    -1     0     0     0     0     0     1     0     0     0

The trick is that the output of diff and your original vector o both have a non-zero value at the same index only for the first occurrence of the value in o (i.e., first occurrence in a chain). So, by multiplying it element-wise with o, you get your answer. The abs is to ensure that a sign change doesn't occur due to the output from diff.

The approach is similar for c, and I'll leave that for you to try :)

Upvotes: 1

flolo
flolo

Reputation: 15526

Usually looping is not more expensive as performing some other operation which just hiddes the loop behind another function (e.g. arrayfun). From your text it just sounds that you just chose the wrong algorithm. Your problem sounds very linear, that is O(n), but you write about loop in loop which means O(n^2). With millions of elements quadratic runtime is not so nice.

The algorithm you want is something like this:

open = 0;

for i=1:length(o)
  if (open == 0) 
     open=o(i)
  else 
     o(i) = 0;
  end
  if (c(i) ~= -open) 
     c(i) = 0;
  else 
     open = 0;
  end
end

It maybe needs some finetunig, as you didnt describe in detail e.g. what the order of the c and o signals are (e.g. if the same index opens and closes is first the open processed or the closed, my example code assumes open), or whether the order of the signals is always ok, or if there must be some error treatment - but I guess you get the idea of the single loop.

Upvotes: 0

Related Questions