Dason のアプローチはクールですが、人間がもっと読みやすいものにしたい場合は、これを使用してください。
`%&%` <- function(e1, e2) ifelse(is.na(e1)|is.na(e2), NA, e1 & e2)
結果:
> x <- c(TRUE, FALSE, NA)
> outer(x, x, `%&%`)
[,1] [,2] [,3]
[1,] TRUE FALSE NA
[2,] FALSE FALSE NA
[3,] NA NA NA
編集:ベンチマーク:
以下に示すように、Dason のアプローチが最速であることに注意してください。
library(microbenchmark)
library(compiler)
x <- sample(c(TRUE, FALSE, NA), size=1e3, TRUE)
y <- sample(c(TRUE, FALSE, NA), size=1e3, TRUE)
`%&1%` <- function(e1, e2) ifelse(is.na(e1)|is.na(e2), NA, e1 & e2)
`%&2%` <- function(x, y) (!x | y) & (x | y) & (x | !y)
`%and%` <- function(x, y)as.logical(x*y)
注:%&2%
運で見つけた面白い代替手段です:-)
これをすべてコンパイルして、何が起こるか見てみましょう。
`%C&2%` <- cmpfun(`%&2%`)
`%C&1%` <- cmpfun(`%&1%`)
`%Cand%` <- cmpfun(`%and%`)
> microbenchmark(x %&1% y, x %&2% y, x %and% y, x %C&1% y, x %C&2% y, x %Cand% y, times=1000)
Unit: microseconds
expr min lq median uq max neval
x %&1% y 201.575 206.124 208.574 211.024 1822.917 1000
x %&2% y 86.439 87.140 87.839 88.190 1244.441 1000
x %and% y 13.299 13.999 14.349 14.700 1141.905 1000
x %C&1% y 200.525 205.775 208.574 210.674 1554.151 1000
x %C&2% y 84.690 85.390 86.090 86.440 1212.596 1000
x %Cand% y 13.299 13.649 14.349 14.699 1141.555 1000
面白いことに、コンパイラはここでは何も変更しません!