【发布时间】:2016-02-03 20:21:47
【问题描述】:
R 中是否有“正确”的 NAND 运算符,例如
nand(condition1, condition 2)
或者它只是最好的做法/唯一的可能性
!(condition1 & condition2)
还有哪些其他选择?
【问题讨论】:
-
你可以定义你自己的。 base 内置的选项都记录在
?Logic(也可以通过?"&"、?"|"或?"!"访问)。
R 中是否有“正确”的 NAND 运算符,例如
nand(condition1, condition 2)
或者它只是最好的做法/唯一的可能性
!(condition1 & condition2)
还有哪些其他选择?
【问题讨论】:
?Logic(也可以通过?"&"、?"|" 或?"!" 访问)。
为了解决这个问题,R 中没有内置的 nand 函数,我能想到的改进您提议的 !(x & y) 的唯一方法是将此操作移至编译语言,例如
#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::LogicalVector nand(Rcpp::LogicalVector lhs, Rcpp::LogicalVector rhs) {
R_xlen_t i = 0, n = lhs.size();
Rcpp::LogicalVector result(n);
for ( ; i < n; i++) {
result[i] = !(lhs[i] && rhs[i]);
}
return result;
}
/*** R
Lhs <- rbinom(10e4, 1, .5)
Rhs <- rbinom(10e4, 1, .5)
r_nand <- function(x, y) !(x & y)
all.equal(nand(Lhs, Rhs), r_nand(Lhs, Rhs))
#[1] TRUE
microbenchmark::microbenchmark(
nand(Lhs, Rhs), r_nand(Lhs, Rhs),
times = 200L)
#Unit: microseconds
# expr min lq mean median uq max neval
# nand(Lhs, Rhs) 716.140 749.926 1215.353 771.015 1856.734 6332.284 200
#r_nand(Lhs, Rhs) 3337.494 3397.809 5106.614 3461.845 4985.807 95226.834 200
*/
这是否值得麻烦可能取决于您需要多久致电一次nand。对于大多数目的,上述r_nand 就足够了。其实base::xor的实现方式类似:
base::xor
#function (x, y)
#{
# (x | y) & !(x & y)
#}
#<bytecode: 0x2fbbb90>
#<environment: namespace:base>
【讨论】:
r_nand 快几微秒。
identical(nand(NA, TRUE), r_nand(NA, TRUE))
!(x & y) 的所有功能 - 例如不等长向量的元素回收 - 结果可能会获得一些性能优势.但话又说回来,我不确定我是否同意 R 在这种情况下对 NAs 的处理:!(NA & FALSE) 返回 TRUE 和 !(NA & TRUE) 返回 NA。我认为在这两种情况下都返回NA 会更明智、更一致。
nand 运算符:`%nand%` <- function(x,y) !(x & y),它可以像这样使用:a %nand% b。 (仅供参考,如果其中一个参数是 NA 而另一个是 TRUE 或 NA,则返回 NA。)