Reputation: 71
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.
Upvotes: 2
Views: 138
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:
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
The second task was to "wipe" (change to 0
) all singleton 1
s, if they are followed by a group of at least two 1
s:
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
.
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
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