Simple logical condition flag MATLAB - matlab

I require help to develop some logic on the below data extract. I need the C2 column to toggle to '1' when C1 is '1'. Then, when C1 is '-1' the C2 column toggles to '0'. All rows in C2 between the C1 toggles (1 & -1) needs to turn to '1'.
Date C1 C2
'24-Dec-1999' 0 0
'31-Dec-1999' 1 1
'07-Jan-2000' 0 1
'14-Jan-2000' 0 1
'21-Jan-2000' 0 1
'28-Jan-2000' 0 1
'04-Feb-2000' -1 0
'11-Feb-2000' 0 0
'18-Feb-2000' 0 0
'25-Feb-2000' 0 0
I used the following, however it only changes the first and last entries on 31-DEC-1999 and 04-FEB-2000. How do I make it so that the entries in between (7-Jan-2000 to 28-Jan-2000) in C2 are also listed as '1'?
C2(C1==1)=1;
C2(C1==-1)=0;

Update
The easiest way to do this is calculate the cumulative sum
C2 = cumsum(C1);
Original / Alternative
You can find the indices where C1=1 and where C1=-1, per your comments there should be an equal number of these
idxStart = find(C1=1); % Could use >0.5 to avoid numerical precision issues
idxEnd = find(C1=-1); % Could use <-0.5 to avoid numerical precision issues
Then you just need to loop through them and make C2=1 in between
C2 = zeros(size(C1));
for ii = 1:numel(idxStart)
C2(idxStart(ii):idxEnd(ii)-1) = 1;
end

Related

MATLAB - Create repeated sequences of ones and zeros with loops

I am trying to create a single column vector (out), which is comprised of a sequence of ones and zeros. These should occur in sets of length B and C respectively, which are repeated A number of times. For example:
out=[1
0
0
1
0
0
1
0
0]
It is currently set up as:
out=[0]; %not ideal, but used to initially define 'out'
A=3;
B=1;
C=2;
for i = 1:length(A)
for ii = 1:length(B)
out(end+1,1) = ones(ii,1);
end
for iii = 1:length(C)
out(end+1,1) = zeros(iii,1);
end
end
This is not working - current output:
out=[0
1
0]
How can I correct these loops to get the desired output? Also, is there a better way of achieving this with the given the inputs?
Many thanks.
1) You do not need to use length as this returns the length of an array type, so A,B,C will all be length of 1.
2) Just directly use the values as shown below. Also you can initialize an empty array with empty brackets []
3) If you're using the zeros and ones commands, these generate whole arrays/matrices and do not need to be in a loop. If you want to keep your loop version, just use =1 or =0
out=[]; %--> you can use this instead
A=3;
B=1;
C=2;
for i = 1:A
out(end+1:end+B,1) = ones(B,1);
out(end+1:end+C,1) = zeros(C,1);
end
... or of course to be more "Matlaby" just do what David said in the comments repmat([ones(B,1);zeros(C,1)],A,1), but the above is there to help you on your way.
How about some modulo arithmetic?
result = double(mod(0:(B+C)*A-1, B+C)<B).';
Example:
>> B = 2; %// number of ones in each period
>> C = 4; %// number of zeros in each period
>> A = 3; %// number of periods
>> result = double(mod(0:(B+C)*A-1, B+C)<B).'
result =
1
1
0
0
0
0
1
1
0
0
0
0
1
1
0
0
0
0
I can suggest 2 ways:
a)Using for loop-
A=3;
B=2;
C=3;
OneVector=ones(1,B); % B is the length of ones.
zeroVector=zeros(1,C); % C is the length of zeros.
combinedVector=cat(2,OneVector,zeroVector);
Warehouse=[]; % to save data
for(i=1:A)
Warehouse=cat(2,Warehouse,combinedVector);
end
b)using repmat:
OneVector=ones(1,B); % B is the length of ones.
zeroVector=zeros(1,C); % C is the length of zeros.
combinedVector=cat(2,OneVector,zeroVector);
Warehouse=repmat(combinedVector, [A,1]);
I hope, this will solve your problem.

Comparing values across unequal matrices in Matlab

I would like to compare rows across two unequal matrices in Matlab and extract these rows to be stored in a different matrix (say D). For example,
tmp = [2245; 2345; 2290; 4576]
and
id=[1 2245 564 8890 123;
2 2445 5673 7846 342;
3 2290 3428 3321 908].
Id is a much larger matrix. I want to locate each value of tmp which is in ‘id’. Although using the intersect command in the line below I have been able to locate the rows of id which contain the values from tmp, I would like to do this for each value of tmp one by one as each value of tmp is repeated multiple times in id. I tried using foreach. However, I get an error message stating that foreach cannot be used for char type array. Could anyone please suggest an alternative how to go about this?
for j=1:length(tmp);
[D,itmp,id2] = intersect(tmp(j,1),id(:,2), 'rows');
Despite using the loop, the code doesn’t seem to take one value of j at a time. This was the reason behind trying ‘foreach j’. Also after finding the rows common to the two matrices and storing them in D, I would like to append matrix id to include the value of j next to the relevant row within id. For example, if the first value within tmp was repeated in id in rows 1,3,5,10; I would like a column in id which would take the value 1 next to rows 1,3,5,10. Any help on this would be much appreciated! Thanks.
Not sure exactly, what you trying to do, but to search a value in a matrix you can use find:
for i = 1:numel(tmp)
[row, col] = find(id == tmp(i));
end
You can easily achieve this using a combination of bsxfun and permute. What you would do is transform the tmp vector so that it is a single 3D vector, then use the eq (equals) function and see which values in your matrix are equal to each value of tmp. Therefore, do something like:
%// Your data
id=[1 2245 564 8890 123;
2 2445 5673 7846 342;
3 2290 3428 3321 908]
tmp = [2245; 2345; 2290; 4576];
tmp2 = permute(tmp, [3 2 1]); %// Make a 3D vector
tmp3 = bsxfun(#eq, id, tmp2); %// Find which locations of id are equal to each value of tmp
This is what I get for my final output, stored in tmp3:
tmp3(:,:,1) =
0 1 0 0 0
0 0 0 0 0
0 0 0 0 0
tmp3(:,:,2) =
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
tmp3(:,:,3) =
0 0 0 0 0
0 0 0 0 0
0 1 0 0 0
tmp3(:,:,4) =
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
As you can see here, each 3D slice tells you which elements in id match the corresponding value in tmp. Therefore, the first slice tells you whether any element in id is equal to tmp(1), which is 2245. In this case, this would be the first row and second column. For the second slice, no values matched tmp(2) = 2345. For the third slice, one value in id matched tmp(3) = 2290, which is row 3, column 3.
Now, what you're really after is determining the rows and columns of where each value of tmp matched each location in id. You want this to be delineated per id number. That can easily be done using ind2sub and find on this matrix:
[rows, cols, ID] = ind2sub(size(tmp3), find(tmp3))
rows =
1
3
cols =
2
2
ID =
1
3
Therefore, ID tells you which id we have matched to, and rows, cols tells you which rows and columns in id we were able to match with. Therefore, for id = 1, we found a match with tmp(1)= 2245, and this is located at row=1,col=2. Similarly, for id = 3, we found a match with tmp(3)=2290 and this is at row=3,col=2.
To make this into all one big 2D matrix that contains all the information you want, you can simply concatenate all of these columns into one matrix. Therefore:
final = [ID rows cols]
final =
1 1 2
3 3 2
You can read this like so:
id=1 with tmp(1) = 2245, we found this value in row=1,col=2.
id=3, with tmp(3) = 2290, we found this value in row=3,col=2
Hope this helps!

How to use logical values and select data in another matrix?

I am getting frustrated with MATLAB when I tried to get the data back in matrix format. But every time i only get back the answer in a single column format. I will illustrate my question:
For example,
A = [1 -3 2;5 4 7;-8 1 3];
L = logical(mod(A,2))
L =
1 1 0
1 0 1
0 1 1
now I have another set of matrix sample called B, C is the output I would like to see
B = [100 300 200;500 400 700;800 100 300];
C = B(L)
C =
100
500
300
100
700
300
I don't want it to remain as a single column. I wonder what I can do to make C returned to me in this matrix format?
C =
100 300 0
500 0 700
0 100 300
Thanks a lot, guys!!!
Logical indexing will select only the elements from the matrix for which the logical matrix is true. Obviously this means it can't retain it's original shape, since the number of elements will change. There are a few ways of doing what you want to do; the most efficient is probably:
C = B;
C(~L) = 0;
This sets C to B, then sets every element of the matrix for which L is false to zero.
Or you could start with a blank matrix and set the desired elements:
C = NaN(size(B),'like',B); % or zeros(size(B),'like',B)
C(L) = B(L);

change a value by a probability value in matlab

I want to change a variable by probability value,
as a example I have [ 0 0 1 1 1 1 0 1 ] in matlab and with probability = 0.01 change any elemet of it , how can I achive this in matlab?
(I want use this in GA and with p =0.01 do mutation of Gen of choromosome )
appreciate any help
First, identify all the elements you want to change
array = [0 0 1 1 1 1 0 1];
sizArray = size(array);
probability = 0.01;
toChangeIdx = rand(sizArray) < probability;
Then, you can flip zeros and ones where needed
array(toChangeIdx) = 1-array(toChangeIdx);
The relevant condition for your code is
if rand() < probability
% Flip your bit here, e.g.
% bitToFlip = randi(length(genome));
% genome(bitToFlip) = 1 - genome(bitToFlip);
end
This will run the code inside the if statement with a probability of exactly probability.

I Need help Numeric Comparison in matlab

I have one matrix called targets (1X4000); column 1 to 2000 contains double value 0 and column 2001 to 4000 contains double value 1
a)
i want to create a matrix called targets_1 where i want to check if the value is 0 then make the entry 1 so at the end of the day i must have a matrix with :column 1 to 2000 with value 1 and column 2001:4000 with value zero
b)
Same situation as above but this time i want to check if the value is 1 then make the entry 1 and if it is zero then make the entry zero; at the end; my new matrix targets_2 contains values: column 1 to 2000 with value zero and column 2001:4000 with value 1
i know how to use the strcmp function to make such checking with strings, but problem is that my original matrix is double and i dont know if there is such function like
setosaCmp = strcmp('setosa',species);
which could work with double (numbers); any help would be appreciated
Your question isn't very clear. It sounds like the following would satisfy your description:
targets_1 = 1 - targets;
targets_2 = targets;
targets1 = double(targets == 0);
targets2 = targets;
I'm basing this answer purely on the fact that you've mentioned setosaCmp = strcmp('setosa', species);. From this I'm guessing that
You have Statistics Toolbox, as setosa is a species of iris from the Fisher Iris dataset widely used in Statistics Toolbox demos, and
You have a variable containing class labels, and you'd like to construct some class indicator variables (i.e. a new variable for each class label, each of which is 1 when the item is in that class, and 0 when it's not).
Is that right? If not, please ignore me.
If I'm right, then I think the command you're looking for is dummyvar from Statistics Toolbox. Try this:
>> classLabels = [1, 2, 1, 2, 3, 1, 3];
>> dummyvar(classLabels)
ans =
1 0 0
0 1 0
1 0 0
0 1 0
0 0 1
1 0 0
0 0 1