什么时候需要在if语句周围加括号来控制R中公式的顺序?

什么时候需要在if语句周围加括号来控制R中公式的顺序?,r,if-statement,sequence,R,If Statement,Sequence,我试图将一个数字除以两个if语句的结果之和。出于某种原因,在完成第一条if语句后,R将忽略两条if语句周围的括号,并仅对第一条if语句进行除法。在第一个if语句周围添加括号时,公式按预期工作。 问题是:为什么会这样 用ifelse(y==2,4,1)替换if语句可以解决这个问题,也可以解决额外的括号问题。我很好奇为什么第一次考试给了我意想不到的结果 x <- 1 y <- 2 z <- 4 test1 <- z/(if(y==2){4}else{1}+if(x==1)

我试图将一个数字除以两个if语句的结果之和。出于某种原因,在完成第一条if语句后,R将忽略两条if语句周围的括号,并仅对第一条if语句进行除法。在第一个if语句周围添加括号时,公式按预期工作。 问题是:为什么会这样

用ifelse(y==2,4,1)替换if语句可以解决这个问题,也可以解决额外的括号问题。我很好奇为什么第一次考试给了我意想不到的结果

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

x第二条语句返回z/(4+4),因此为0.5,对于第一条语句,它只计算第一个if()子句。证明:

> z/(if(y==2){4}else{1}+if(x==1){4}else{3})
[1] 1

一个很好的问题。从:


R中的计算由顺序求值语句组成。陈述,比如x另一种看待它的方式:对我来说,它归结为以下事实:

  • {
    用于对语句进行分组,而不是对它们进行分隔
  • 它不是控制流构造或函数定义语法的一部分,正如括号所示,尽管标准用法通常看起来是这样的
  • 本质上,控制流符号对语句进行分隔,因此其优先级低于任何运算符,请参见:
lobstr::ast(如果为(TRUE)1,则为0+4)
#>o-‘如果’
#>+-正确
#> +-1 
#>\-o-`+`
#>   +-0 
#>   \-4
lobstr::ast(如果(TRUE)1 else{0}+4)
#>o-‘如果’
#>+-正确
#> +-1 
#>\-o-`+`
#>+-o-`{`
#>   | \-0 
#>   \-4
lobstr::ast(if(TRUE)1 else{0}+-TRUE
#> +-1 
#>\-o-`+-o-`{`
#>   | \-0 
#>   \-4
lobstr::ast(if(TRUE)1 else{0}?4)#``在运算符中具有最低的优先级
#>o-‘如果’
#>+-正确
#> +-1 
#>\-o-`?`
#>+-o-`{`
#>   | \-0 
#>   \-4
由(v0.3.0)于2019-08-19创建

从这个角度来看,结果并不令人惊讶

为了进一步说明,使用OP的案例:

lobstr::ast(z/(如果(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

由(v0.3.0)于2019-08-19创建此问题引发了对R-devel邮件列表的讨论,

R处理这种情况的方式令人惊讶,因为在if/else和其他一些构造中,如果有大括号,则大括号是要计算的表达式的一部分,而不是语法分隔符。特别是,表达式不一定以大括号结尾。例如,
{2}+3
2+3
是等价的表达式,因此下面的第一个命令给出的是0,而不是3(第二个命令的结果也是0,正如预期的那样)

这种混淆主要出现在“if”结构的“else”部分,但并不限于此。例如,这定义了一个函数体为
x^2+1
,原因相同(
{x^2}+1
相当于
x^2+1
),尽管人们可能会在下面的第一行出现错误:

f <- function(x){x^2} + 1
f(2)
## [1] 5         

f在
test1
中,如果
满足条件(
y==2
),它将永远不会超过第一个
。在
test2
中,它被视为一个单独的块。我已经使用R十年了。我不会预测到这一点。不要用
ifelse(y==2,4,1)
,你可以用
替换为“if”(y==2,4,1)
如果你必须回答这个问题,那么问题是“为什么”?所以在测试1中它基本上说的是:如果Y==2{4}else({1}+if(x==1){4}else{1})。这就是sense@Hugh我的猜测是,括号强制执行一个似乎很重要的特定评估顺序(acts惊奇)。我认为问题在于第一个
if/else
块末尾的右大括号后面的加号。正因为如此
+
,R希望后面有更多的内容。在这种情况下,后面的内容是一个有效的表达式,并进行了计算。
if (y == 2) {
  4
} else {
  1
}
if (y == 2) {
  4
} else {
  1
} -> a
if(TRUE) 0 else {2} + 3
## [1] 0
if(TRUE) 0 else 2 + 3
## [1] 0
f <- function(x){x^2} + 1
f(2)
## [1] 5