【问题标题】:Efficient way to do multiple logical operations执行多个逻辑操作的有效方法
【发布时间】:2020-12-25 22:24:04
【问题描述】:

假设我有三个长度相同的向量

vec1 <- c(1,2,3,10)
vec2 <- c(1,4,5,8)
vec3 <- c("==","<=",">=","==")

我想使用 vec3[x] 中的运算符比较 vec1[x] 和 vec2[x],以检查是否全部为真。我目前的解决方案如下

vec1 <- c(1,2,3,10)
vec2 <- c(1,4,5,8)
vec3 <- c("==","<=",">=","==")

result <- TRUE

for (i in 1:4){
  if (vec3[i] == "=="){
    if (! vec1[i] == vec2[i]) {
      result <- FALSE
      break
    } 
  } else if (vec3[i] == "<=") {
    if (! vec1[i] <= vec2[i]) {
      result <- FALSE
      break
    } 
  } else if (vec3[i] == ">=") {
    if (! vec1[i] >= vec2[i]) {
      result <- FALSE
      break
    }
  }
}

print(result)

输出是

[1] FALSE

它可以工作,但如果向量较大并且您必须做很多事情,它会很慢。有更好的方法吗? 向量的排序方式使得最有可能返回 FALSE 的比较排在第一位。 我要补充一点,实际上向量的长度为 28。vec2 和 vec3 是常数,vec1 是可变的。

【问题讨论】:

  • 这些是你可以做的矢量化操作vec1 == vec2
  • 你可以用any包装

标签: r performance


【解决方案1】:

这可以简化为

f1 <- function(v1, v2, oper) {

  all(Reduce(`&`, lapply(oper, function(op) match.fun(op)(v1, v2))))

 }

f1(vec1, vec2, vec3)
#[1] FALSE

【讨论】:

    【解决方案2】:

    也许你可以像这样尝试eval + call

    all(mapply(function(op, a, b) eval(call(op, a, b)), vec3, vec1, vec2))
    

    Vectorize + do.call

    all(Vectorize(do.call)(vec3, apply(cbind(vec1, vec2), 1, as.list)))
    

    【讨论】:

      【解决方案3】:

      一个purrr 选项可以是:

      all(pmap_lgl(list(vec1, vec2, vec3), ~ exec(..3, ..1, ..2)))
      
      [1] FALSE
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多