为什么ifelse会产生“警告生成的NaN”?

时间:2018-12-20 04:30:00

标签: r

我有一个非常简单的分段函数,该函数采用向量参数omega

btilde <- function(omega) {
        if(min(omega)<=0) stop("ALL ELEMENTS OF OMEGA MUST BE POSITIVE")
        ifelse( 0 < omega & omega <=  1, 0.233*omega^2,
        ifelse( 1 < omega & omega <=  3, 0.005*omega^4 - 0.06906*omega^3 + 0.3167*omega^2 - 0.02326*omega,
        ifelse( 3 < omega & omega <= 40, 0.705*sqrt(omega)*log(omega),
        ifelse(40 < omega,               sqrt(3*omega*log(omega) - log(8*pi) - 2/log(omega) - 170),
        NA))))
    }

如果有omega=c(1,41),但如果有omega=1omega=41,我会得到一个“警告NaN产生”。

> btilde(1)
[1] 0.233
> btilde(41)
[1] 16.8228
> btilde(c(1,41))
[1]  0.2330 16.8228
Warning message:
In sqrt(3 * omega * log(omega) - log(8 * pi) - 2/log(omega) - 170) :
  NaNs produced

如果将“> 40”条件应用于“ omega = 1”,那么可以,我会得到一个NaN,但这不是ifelse()的工作原理,对吗?有人可以帮我了解发生了什么吗?谢谢!

2 个答案:

答案 0 :(得分:3)

我建议您专注于算法中的一个元素,然后将函数map列出。 这是您的方法的另一个版本,没有警告:

library(purrr)

btilde <- function(omega) {
  if (omega <= 0) stop("ALL ELEMENTS OF OMEGA MUST BE POSITIVE")
  if (omega <= 1) return (0.233*omega^2)
  if (omega <= 3) return (0.005*omega^4 - 0.06906*omega^3 + 0.3167*omega^2 - 0.02326*omega)
  if (omega <= 40) return(0.705*sqrt(omega)*log(omega))
  return(sqrt(3*omega*log(omega) - log(8*pi) - 2/log(omega) - 170))
}

以下是输出:

> map_dbl(c(1,41), ~ btilde(.x))
[1]  0.2330 16.8228

答案 1 :(得分:2)

ifelse帮助页面上,

  

只有在“ test”的任何元素为true时(与“ no”类似),才会对“ yes”进行评估。

因此,即使单个元素为FALSE,也可以对表达式求值,即使其他元素为TRUE。考虑简单的例子

x = c(0, -1) 
ifelse(x == 0, sqrt(x), x)

[1]  0 -1
Warning message:
In sqrt(x) : NaNs produced

产生与您的代码类似的警告。