I am trying to divide a number by the sum of the result of two if statements. For some reason, R ignores the parentheses around both the if statements after completing the first if statement and does the division on just the first if statement. When adding parentheses around the first if statement, the formula works as expected. Question is: why is that?
Replacing the if statements with ifelse(y==2,4,1) solves it, as well as the extra parentheses. I am curious why the first test gives me the unexpected result.
x <- 1
y <- 2
z <- 4
test1 <- z/(if(y==2){4}else{1}+if(x==1){4}else{1})
> print(test1)
[1] 1
test2 <- z/((if(y==2){4}else{1})+if(x==1){4}else{1})
> print(test2)
[1] 0.5
I would expect the outcome of test1 and test2 both to be 0.5
An excellent question. From the R Language Definition:
Computation in R consists of sequentially evaluating statements. Statements, such as x<-1:10 or mean(y), can be separated by either a semi-colon or a new line.
Further, under if
:
The if/else statement conditionally evaluates two statements. There is a condition which is evaluated and if the value is TRUE then the first statement is evaluated; otherwise the second statement will be evaluated. The if/else statement returns, as its value, the value of the statement that was selected. The formal syntax is
if ( statement1 ) statement2 else statement3
The issue you encountered is that {1}+if(x==1){4}else{1}
is a valid statement so R interprets this as statement3. In other words, from else
, anything (within the block) up until a newline or a semicolon is only encountered when the if
statement is FALSE.
Normally, in something like
if (y == 2) {
4
} else {
1
}
we understand that after the final brace, the if statement has finished, but it is the newline, not the closing brace, that signifies the end of the expression. For example, this does not create a
if (y == 2) {
4
} else {
1
} -> a
Second statement returns z/(4+4), ergo 0.5 and for the first statement, it evaluates only the first if() clause. Proof:
> z/(if(y==2){4}else{1}+if(x==1){4}else{3})
[1] 1
Another way to look at it : to me it boils down to the fact that :
{
is used to group statements, not delimit them. lobstr::ast(if (TRUE) 1 else 0 + 4)
#> o-`if`
#> +-TRUE
#> +-1
#> \-o-`+`
#> +-0
#> \-4
lobstr::ast(if (TRUE) 1 else {0} + 4)
#> o-`if`
#> +-TRUE
#> +-1
#> \-o-`+`
#> +-o-`{`
#> | \-0
#> \-4
lobstr::ast(if (TRUE) 1 else {0} <- 4) # `<-` has very low precedence amongst operators
#> o-`if`
#> +-TRUE
#> +-1
#> \-o-`<-`
#> +-o-`{`
#> | \-0
#> \-4
lobstr::ast(if (TRUE) 1 else {0} ? 4) # `?` has the lowest precedence amongst operators
#> o-`if`
#> +-TRUE
#> +-1
#> \-o-`?`
#> +-o-`{`
#> | \-0
#> \-4
Created on 2019-08-19 by the reprex package (v0.3.0)
In this light the result is not that surprising.
To illustrate further, using OP's case :
lobstr::ast(z/(if(y==2){4}else{1}+if(x==1){4}else{1}))
#> o-`/`
#> +-z
#> \-o-`(`
#> \-o-`if`
#> +-o-`==`
#> | +-y
#> | \-2
#> +-o-`{`
#> | \-4
#> \-o-`+`
#> +-o-`{`
#> | \-1
#> \-o-`if`
#> +-o-`==`
#> | +-x
#> | \-1
#> +-o-`{`
#> | \-4
#> \-o-`{`
#> \-1
Created on 2019-08-19 by the reprex package (v0.3.0)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With