How to cumulatively add consecutive ones between zeros in a logical vector

3 vues (au cours des 30 derniers jours)
Shawn
Shawn le 26 Oct 2017
Commenté : Shawn le 27 Oct 2017
I have a vector that looks like
x = [0 0 1 1 0 0 1 1 1 0 0 1]
and am trying to obtain
y = [0 0 1 2 0 0 1 2 3 0 0 1]
without using a loop. Any help would be much appreciated. The answer by Roger Stafford in https://www.mathworks.com/matlabcentral/answers/118828-how-to-count-the-number-of-consecutive-numbers-of-the-same-value-in-an-array is along the lines of what I am trying to achieve, but I am currently unable to manipulate his code to serve my purpose.

Réponse acceptée

Andrei Bobrov
Andrei Bobrov le 26 Oct 2017
y = x(:)';
ii = accumarray(bwlabel(y(:))+1,1);
y = [y,0];
y(strfind(y,[1 0])+1) = -ii(2:end);
out = cumsum(y(1:end-1));
  4 commentaires
Shawn
Shawn le 26 Oct 2017
Thank you very much! This is excellent.
Shawn
Shawn le 27 Oct 2017
I added comments to the code in case anyone else is trying to understand it since it took me quite some time to understand the logic.
%%Cumulatively Add Consecutive Ones Between Zeros in a Logical Vector
x = [1 1 0 0 0 0 0 1 1 1 1 0 1 1 0 1 1 0 1 1 1 0 1 0 1 0 1 0 0 1 1 1];
%diff([0;x(:)]) vertically concatenates, adds a leading 0, and then
%takes the difference between consecutive points
%cumsum(diff([0;x(:)]) == 1) finds the location of each change from 0 to 1,
%keeps that value constant elementwise until another 0 to 1 shows up, and
%then increments by 1 each time it shows up
%cumsum(diff([0;x(:)]) == 1).*x(:) elementwise multiplies the previous
%equation by the original vector, which will set corresponding 0 elements
%to 0
%accumarray(cumsum(diff([0;x(:)]) == 1).*x(:)+1,1) adds one to the previous
%equation and then creates histogram style binning of the appearance of
%each number from 1 on (since 1 was added, the index corresponds to one
%more than the actual number)
ii = accumarray(cumsum(diff([0;x(:)]) == 1).*x(:)+1,1);
%adds a trailing 0 to the original vector
y = [x,0];
%strfind(y,[1 0])+1 finds the locations of every instance of a 1 then a 0
%showing up and then adds 1 to get the indeces of that 0
%y(strfind(y,[1 0])+1) = -ii(2:end) replaces the previously described 0
%indeces with the negative of the corresponding bin number of how many
%times in a row the number 1 was repeated prior to it (recall that the
%index is one greater than the actual number and that we counted up from 1
%every time that a 0 to 1 showed up)
y(strfind(y,[1 0])+1) = -ii(2:end);
%now we cumulatively add each number together, so whenever we have ones
%they will add and then thanks to the last step, the 0 following a 1
%contains the negative of the number of ones that preceeded it, so it will
%reset the count to 0
out = cumsum(y(1:end-1));

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Logical dans Help Center et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by