有没有办法短路矢量化操作数(&和&&)的组合?

时间:2018-05-07 10:11:20

标签: r vectorization

在R中,有操作数和&和&& (或者,|和||),其中&是矢量化的,&&不是。另一个区别是&总是评估所有参数,而&&短路(有时称为懒惰评估),意味着F&& fun(x)不会打电话给乐趣(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") 

在这里,我收到警告,因为&#39;呵呵&#39;虽然&#39; huh&#39;但是不能用数字表示。永远不需要执行该功能。

我喜欢的是与此类似的行为:

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:

mapply(`&&`, input$valid, fun(input$value))

但仍然有趣的是评价。 值得注意的是,必要时&amp;&amp;和&amp;&amp ;;如果您比较以下内容:

mapply(`&&`, c(F,F), c(T, print('Huh?')))
mapply(`&&`, c(T,T), c(T, print('Huh?')))
mapply(`&`, c(F,F), c(T, print('Huh?')))

但是在所有情况下都要对印刷品进行评估,我想是对力度进行评估。

我也试过这个:

`%&%` <- 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首先进行评估,然后进行子集化... (是的,我知道我也应该检查长度,我正在尝试这个,因为可能长度检查是强制评估)

1 个答案:

答案 0 :(得分:1)

你可以做的是创建一个新函数的构造函数,将NA作为FALSE处理:

bool_noNA <- function(fun) {
  function(x, valid) {
    if (missing(valid)) valid <- !is.na(x)
    res  <- logical(length(x))
    res[valid] <- fun(x[valid])
    res
  }
}

使用示例:

is_odd <- function(x) x %% 2 == 1    
is_odd(c(3:5, NA))

is_odd_noNA <- bool_noNA(is_odd)
is_odd_noNA(c(3:5, NA))
is_odd_noNA(c(3:5, NA), valid = c(T, F, F, F))
is_odd_noNA(c(3:5, NA), valid = c(F, T, F, F))