Why is this MATLAB 'if' statement not working?
I am new to MATLAB and I cannot figure out why my if statement and condition are not working. I have a 100 by 4 matrix ( randQ
). Columns 1
thru 3
are random integers and column 4 contains either 1 or 2 in each row.
I want to change everything 1
to 0
and everything 2
to 1
in a column 4
in this 100 by 4 matrix. What I do:
if randQ(:,4) == 1
randQ(:,4) = 0
elseif randQ(:,4) ==2
randQ(:,4) = 1
end
It doesn't throw any errors, but the matrix doesn't change and the conditions make sense in my opinion. I don't know why it doesn't work. Any explanations would be appreciated.
source to share
Renouncement
Some of the other answers contain incorrect / imprecise statements:
- you are trying to compare a vector to a scalar which will never be true.
- You are asking if your vector doesn't match == 1.
As an example,
if [1, 1, 1] == 1
disp("True")
end
will display "True"
. Below is an explanation.
You write
I cannot figure out why my "if" statement and condition are not working
What's really going on is pretty subtle. You need to develop an understanding of several things:
- what the expression returns
randQ(:,4) == 1
, - what the if if statement does when presented with a predicate that is not a scalar but an array,
- what
randQ(:,4) = 0
does it do.
Also, you need to use logical indexing for this kind of operations .
What randQ(:,4) == 1
returns
Assuming it randQ
is a 100 by 4 randQ(:,4) == 1
array , the expression returns a boolean array , i.e. complete (logical) zeros and ones:
- if the i-th record of this array is (boolean)
1
, it means that the record (i, 4)randQ
is1
; - if the i-th element of this array is (boolean)
0
, it means that the record (i, 4) israndQ
not equal1
.
Array as a predicate
Now that you know you are using an array for an if statement predicate, let's see what happens. If the predicate of your if statement is an array, MATLAB will execute the if clause only if all entries in that array evaluate to boolean1
.
For example,
if [1, 2; 3, 4]
disp("True")
else
disp("False")
end
will display "True"
because all records [1,2;3,4]
are returned as boolean 1
, which causes the predicate to evaluate to boolean 1
(true). Nevertheless,
if [1, 2; 3, 0]
disp("True")
else
disp("False")
end
display "False"
, because the record (2.2) from [1,2;3,0]
receives as logic 0
that causes the predicate is evaluated as a logical 0
(false). Therefore, if at least one entry in randQ(:,4)
is equal to zero, if
it will not be executed.
Assignment attributes are wrong anyway
Assignment operator
randQ(:,4) = 0
will overwrite all entries in the 4th column with using 0
, which is not what you want.
Better approach: use boolean indexing
You write
I want to change all 1 to 0 and all 2 to 1 in column 4 in this 100 by 4 matrix.
A more idiomatic approach for this, as pointed out by giuseppe , is to use boolean indexing :
randQ(randQ(:,4) == 1, 4) = 0;
randQ(randQ(:,4) == 2, 4) = 1;
There is no need to use the function find
because it randQ(:,4) == 1
already returns what you want: a 100-by-1 boolean array indicating which entries in the 4th column randQ
are equal 1
.
source to share
The result randQ(:,4)
is a vector with length 100. Then you try to compare it to a scalar, which will only be true if all the terms of the vector (or matrix) are equal to the scalar.
> M=[1 1; 2 1; 3 2]
M =
1 1
2 2
3 1
> M(:,1)
ans =
1
2
3
Also, the way you are trying to change the values ββis wrong, if you do randQ(:,4) = 1
then the whole 4th th column will get the value 1:
>M(:,2)=0
M =
1 0
2 0
3 0
The easiest way to achieve what you want is to loop through the matrix line by line, check the value and then change it.
source to share
Like the other answers, you are trying to compare a vector to a scalar, this will never be true.
Instead, you can achieve your goal with the Find function , this function actually implements element comparison.
randQ(find(randQ(:,4) == 1),4) = 0;
randQ(find(randQ(:,4) == 2),4) = 1;
source to share