【发布时间】:2018-05-15 17:57:21
【问题描述】:
在 R 中,有操作数 & 和 &&(或者,| 和 ||),其中 & 是矢量化的,而 && 不是。另一个区别是 & 总是计算所有参数,而 && 短路(有时称为惰性计算),这意味着 F && fun(x) 不会调用 fun(x)。
我正在寻找的是结合这两者的方法,例如我可以调用的方法
input <- data.frame(valid=c(T,T,T,F,F), value=c('1','2','3','huh',14), stringsAsFactors = F)
# A function to check evenness, but who prints an alert if the value is more then 10
fun <- function(x) {
if(any(as.numeric(x)>10))
cat(as.numeric(x)[as.numeric(x)>10], '')
return(as.numeric(x) %% 2==0)
}
cat("Numbers over 10 (unexpected):\n")
pass <- input$valid & fun(input$value)
cat("\nAnd in total we have",sum(pass),"even numbers")
在这里,我收到警告,因为 'huh' 不能转换为数字,即使执行函数永远不需要 'huh'。
我想要的是类似这样的行为:
pass2 <- rep(FALSE, nrow(input))
cat("Numbers over 10 (unexpected):\n")
for(n in 1:nrow(input)) {
if(input$valid[n]) pass2[n] <- fun(input$value[n])
}
cat("\nAnd in total we have",sum(pass2),"even (valid) numbers")
在这个例子中,很容易适应乐趣,或者围绕它来写,但在我的日常工作中,我经常发现有更困难的条件的用例,以及我不想每次都适应的各种功能。
有什么方法可以做我想做的事,还是我真的需要返回到非向量化函数和/或 for 循环?
我自己尝试了一些方法,但没有成功: 映射:
mapply(`&&`, input$valid, fun(input$value))
但仍会评估乐趣。 有趣的是,如果您比较以下内容,则 && 在必要时会忽略返回的值:
mapply(`&&`, c(F,F), c(T, print('Huh?')))
mapply(`&&`, c(T,T), c(T, print('Huh?')))
mapply(`&`, c(F,F), c(T, print('Huh?')))
但在所有情况下,打印都会被评估,我猜是 mapply 强制评估。
我也试过这个:
`%&%` <- function(a,b) {
res <- rep(FALSE, times=length(a))
res[is.na(a)|a] <- a[is.na(a)|a] & b[is.na(a)|a]
}
input$valid %&% fun(input$value)
认为如果 a 不为假,我只会使用 b 的值。 但看起来这里发生的事情几乎相同:首先评估 b ,然后才进行子集化...... (是的,我知道我也应该检查长度,我正在尝试这个,因为长度检查可能会强制评估)
【问题讨论】:
-
您可以考虑在您的问题中包含reproducible example。这会让其他人更容易帮助你。
标签: r vectorization