This is a good problem, and since @rayryeng did not offer a vectorized solution, here's mine in a few lines - okay, this is dishonest, it took me half a day to finish this. The basic idea is to use cumsum as the final function.
p = size(hypwayt,2); % keep nb of columns in mind % H1 is the mask of consecutive identical values, but kept as an array of double (it will be incremented later) H1 = [zeros(1,p);diff(hypwayt)==0]; % H2 is the mask of elements where a consecutive sequence of identical values ends. Note the first line of trues. H2 = [true(1,p);diff(~H1)>0]; % 1st trick: compute the vectorized cumsum of H1 H3 = cumsum(H1(:)); % 2nd trick: take the diff of H3(H2). % it results in a vector of the lengths of consecutive sequences of identical values, interleaved with some zeros. % substract it to H1 at the same locations H1(H2) = H1(H2)-[0;diff(H3(H2))]; % H1 is ready to be cumsummed! Add one to the array, all lengths are decreased by one. Output = cumsum(H1)+1; % last force input zeros to be zero Output(hypwayt==0) = 0;
And the expected result:
Output = 1 1 1 1 1 1 1 2 2 2 2 2 3 0 0 1 1 0 1 1 1 1 0 0 0 1 1 1 1 1 1 2 0 1 2 0 3 1 2 3 1 0 1 3 0 1 1 0 1 1
Let me add some explanation. The big trick, of course, is the second, it took me a while to figure out how to quickly calculate the lengths of consecutive identical values. The first one is just a little trick to figure it all out without any cycles. If you cumsum H1 directly, you will get the result with some offsets. These offsets are removed using the cumsum-compatible method, using the local difference in some key values ββand removing them immediately after the ends of these sequences. These special values ββare numbered, I also take the first row (the first row of H2 ): each element of the first column is considered different from the last element of the previous column.
Hopefully this will become clearer now (and there is no shortage in some special case ...).
source share