即使满足测试条件,ifelse也会根据else函数显示警告

时间:2017-07-14 07:44:49

标签: r if-statement warnings vectorization

我有一个矢量。例如,

a = c(5,-5)

我想根据a>0是否

对a的值执行不同的功能

为简单起见,假设功能如下

output = ifelse(a>0, log(1+a), 0)

此代码返回所需的值,该输出等于

1.791759 0.000000

但是,它也显示警告:

Warning message:
In log(1+a) : NaNs produced

我希望有人能够解释为什么这个警告会显示,尽管事件log(1+a)只会在a>0(不会产生NaN)时被调用。这是ifelse的奇怪怪癖还是我做错了什么。

我还要注意,当a的两个元素都小于0时,不会发生此警告(例如a=c(-5,-5)

1 个答案:

答案 0 :(得分:2)

关于ifelse的实施,这是一个古怪的事情。

如果我们查看函数,我们可以看到负责实际输出的部分:

> ifelse
function (test, yes, no) 
{
    if (is.atomic(test)) {
        if (typeof(test) != "logical") 
            storage.mode(test) <- "logical"
        if (length(test) == 1 && is.null(attributes(test))) {
            if (is.na(test)) 
                return(NA)
            else if (test) {
                if (length(yes) == 1 && is.null(attributes(yes))) 
                  return(yes)
            }
            else if (length(no) == 1 && is.null(attributes(no))) 
                return(no)
        }
    }
    else test <- if (isS4(test)) 
        methods::as(test, "logical")
    else as.logical(test)
    ans <- test
    ok <- !(nas <- is.na(test))
    if (any(test[ok])) 
        ans[test & ok] <- rep(yes, length.out = length(ans))[test & 
            ok]
    if (any(!test[ok])) 
        ans[!test & ok] <- rep(no, length.out = length(ans))[!test & 
            ok]
    ans[nas] <- NA
    ans
}

这是相关部分:

    ans <- test
    ok <- !(nas <- is.na(test))
    if (any(test[ok])) 
        ans[test & ok] <- rep(yes, length.out = length(ans))[test & 
            ok]
    if (any(!test[ok])) 
        ans[!test & ok] <- rep(no, length.out = length(ans))[!test & 
            ok]
    ans[nas] <- NA
    ans

test的布尔结果存储在ans中。然后有一些关于是否有na结果的检查,这与此无关。然后基于布尔值创建结果向量。但看看完成的方式。

对于TRUE结果:

ans[test & ok] <- rep(yes, length.out = length(ans))[test & ok]
评估并重复

yes以使其与输出长度匹配,然后进行子集化以获取测试中TRUE的项目。

生成警告的位置就在这里。 ifelse会评估log(-5 + 1),生成警告,但会将其从结果中排除,因为test = FALSE

请注意,如果所有条目都是FALSE,则if语句if (any(test[ok]))会阻止执行该部分,因此不会对yes参数进行评估,也不会发出警告。