a.kk
a.kk

Reputation: 71

Changing subsequent 1's to 0's in binary data

Hi I have a binary variable (called 'column' size 733x1) and in order to change the 0's in-between where I have 1's to 1's (i.e. 00001110011... to 00001111111...). I am using:

column_fill = column;
column_fill(find(column == 1, 1):find(column == 1, 1, 'last')) = 1;

I would like to change this to if there is a series of 1's within my variable followed by a series of 5 or more 0's, all further 1's are changed to 0's. Link to data. Output (from 000..0001110000011101... to 000..0000000000011111...) Thanks.

Also I would appreciate help with adding an extra part (for somewhere else in my code) if there are single 1's before a group of 1's then change them to 0's. Output (from 000..000111110001 to 000..000111110000). Thank you.

data 2

Upvotes: 2

Views: 138

Answers (2)

EBH
EBH

Reputation: 10440

Here is a general way to "ask questions" on your column100 vector. I make a small set of variables that conclude all information on this vector in a summarized way, that makes all this kind of testing more easy:

First, I create three vectors with the basic information:

row_c = fliplr(column100.'); % your questions are "right to left" (The .' is not really needed)
d = diff([row_c(1) row_c]); % find all switches between 1 to 0 or 0 to 1
len = 1:numel(row_c); % make a list of all indices in row_c
idx = [len(d~=0)-1 numel(row_c)] % the index of the end each group
counts = [idx(1) diff(idx)] % the number of elements in the group
elements = row_c(idx) % the type of element (0 or 1)
n_groups = numel(idx) % the no. of groups in the vector

the output so far:

idx =
   195   199   205   207   235   256   272   733
counts =
   195     4     6     2    28    21    16   461
elements =
     1     0     1     0     1     0     1     0
n_groups =
     8

So we can see the data is made of 8 groups, and, for example, the third group goes from 200:205, it is a group of 1, and it has 6 elements.

Now we can perform different tasks with this data:

Task 1

Our first task was to find groups (counts>2) of 1 that are followed by a group of at least 5 0:

for k = 1:n_groups-1
    % elements(k) --> is this a group of '1'? (it will always be followed by a '0')
    % counts(k)>1 --> is this a series of at least '11'?
    % counts(k+1)>4 --> is it followed by at least '00000'?
    if elements(k) && counts(k)>1 && counts(k+1)>4
        row_c(idx(k)+1:end)=0; % if so, change all following '1' to zeros
        break % and end the loop since all following pairs were removed.
    end
end

and we can check and see (by running the code above again without the first line) that now:

idx =
   195   199   205   207   235   733
counts =
   195     4     6     2    28   498
elements =
     1     0     1     0     1     0
n_groups =
     6

Task 2

The second task was to "wipe" (change to 0) all singleton 1s, if they are followed by a group of at least two 1s:

for k = 1:n_groups-2
    % elements(k) --> is this a group of '1'?
    % counts(k)==1 --> is it single?
    % counts(k+2)>1 --> the next '1' is not single?
    if elements(k) && counts(k)==1 && counts(k+2)>1
        row_c(idx(k))=0; % change the single '1' to '0'.
    end
end

The data don't include any single 1, but if it had this code will change it to 0.

Task 3

This is from your comment to @Tasos answer - change all 0 prior to the last 1 to 1:

for k = n_groups:-1:1
    if elements(k) % is this the last group of '1'?
        row_c(1:idx(k))=1; % change all prior '0' to '1'
    end
end

again we can check and see (by running the first block of code above again without the first line):

idx =
   272   733
counts =
   272   461
elements =
     1     0
n_groups =
     2

now we have only two groups, one of all the 0 after the last 1, and one for all the rest of the vector that is now changed to 1.

Upvotes: 2

Tasos Papastylianou
Tasos Papastylianou

Reputation: 22215

You could probably convert to a string sequence and use string /regexp operations. e.g.:

c = char(column100'+48);                % convert to string
C = regexp(c, '1.+00000', 'match');     % regular expression.
c2 = strrep(c,C{1},strrep(C{1},'1','0')); % assumes 1 match here, adapt
                                          % appropriately for general case
newcolumn = logical(double(c-48)'); % convert back to logical vector.

Similarly you can use a '010.*' regexp for the second bit.
If you don't know what regular expressions are, type help regexp

Upvotes: 1

Related Questions