2013-06-17 12 views
7

Czy istnieje operator logiczny, który daje mi NA, jeśli którakolwiek z części to NA? ObecnieOperator Boolean rozpoznający NA

NA & FALSE == FALSE 
FALSE & NA == FALSE 
NA & TRUE == NA 
TRUE & NA == NA 

chciałbym posiadać:

NA x FALSE == NA 
FALSE x NA == NA 

PS:

Szukam dla operatora x, dla których

x  | a=TRUE | =FALSE | =NA 
----------------------------------- 
b=TRUE | TRUE | FALSE | NA 
=FALSE | FALSE | FALSE | NA 
=NA | NA | NA | NA 

więc mogłem zrobić

result <- a x b 
+1

Byłoby pomocne umieszczenie tego w rzeczywistej składni R, więc jasne jest, o co prosisz. – Thomas

+2

możesz wypróbować 'any' ...' xx <- c (1,2,3, NA, 4,5); any (is.na (xx)) ' – Arun

+1

@Arun' any' jest rozszerzeniem '|', a '| 'działa tak, jak chce Hoffmann. Rozszerzenie '&' jest 'all' i ma ten sam numer – Dason

Odpowiedz

9

Można zdefiniować własnego operatora, który robi to, co chcesz.

> `%and%` <- function(x, y){as.logical(x*y)} 
> NA %and% FALSE 
[1] NA 
> FALSE %and% NA 
[1] NA 
> NA %and% TRUE 
[1] NA 
> TRUE %and% NA 
[1] NA 
6

podejście Dason jest fajne, ale jeśli chcesz coś bardziej czytelnego przez śmiertelników, użyj tego:

`%&%` <- function(e1, e2) ifelse(is.na(e1)|is.na(e2), NA, e1 & e2) 

Wyniki:

> x <- c(TRUE, FALSE, NA) 
> outer(x, x, `%&%`) 
     [,1] [,2] [,3] 
[1,] TRUE FALSE NA 
[2,] FALSE FALSE NA 
[3,] NA NA NA 

EDIT: Benchmarking:

Powinno należy zauważyć, że podejście Dason'a jest najszybsze, jak pokazano poniżej:

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) 

Uwaga: %&2% to zabawna alternatywa Właśnie znaleźć szczęścia :-)

Niech skompilować wszystko to, aby zobaczyć co się stało:

`%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 

Zabawne, kompilator nie zmienia cokolwiek tutaj!

+0

Pewnie! Moją główną sugestią było to, że możemy zbudować własnego operatora, ponieważ nie sądzę, że jest zbudowany, który robi to, co chcemy. Algebra boolowska w mojej odpowiedzi nie powinna być zbyt trudna do naśladowania, aw każdym razie łatwo jest zbudować tabelę prawdy (tak jak ty), aby zobaczyć, że daje ona pożądaną odpowiedź. Dobra alternatywa! – Dason

+0

@Dason i twoja odpowiedź jest najszybsza, patrz edytuj powyżej! –