我有一个矢量。例如,
a = c(5,-5)
我想根据a>0
是否
为简单起见,假设功能如下
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)
)
答案 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
参数进行评估,也不会发出警告。