Data Blue

データの海で遊んでます。

Rの論理判定は欠損値があるときには注意

解析に回す前にデータクリーニングなどを行いますが、 欠損値があるときにAndやOrなどの演算子を使うと、 予期せぬ挙動をすることがあります。 RのNAの処理の仕方が、かなり我々の印象と違います。

例 (irisデータで)

test = iris
test[sample(1:nrow(iris),60, replace=T),1] = NA
test[sample(1:nrow(iris),60, replace=T),2] = NA

上記でランダムに欠損したデータを作ります。 まず、Andについてみてみます。

data.frame(col1=test[,1] > 5, col2=test[,2] > 3,     
A= test[,1] > 5 & test[,2] > 3,    
Product= (test[,1] > 5) * (test[,2] > 3)==1)

結果はランダムに変わりますが、例えばこうなります。

   col1  col2    And  Product
1  TRUE TRUE    TRUE     TRUE
2    NA   NA      NA       NA
3 FALSE   NA   FALSE       NA
4 FALSE TRUE   FALSE    FALSE
5    NA TRUE      NA       NA
6  TRUE   NA      NA       NA

3行目3列目に注目していただくと、普通の&でつないだだけの論理演算子は、
FALSE & NA = FALSE
となっていますが、 直感的にはどちらかがNAであれば結果もNAに
なってほしいところです。
ifelseなどのif文でこのようなデータ処理をしがちで危険です。
この場合、4列目のように掛け算を使うことで回避できます。

一方、Orの演算子|については、

data.frame(col1=test[,1] > 5, col2=test[,2] > 3,    
 Or= test[,1] > 5 | test[,2] > 3, 
 Add= (test[,1] > 5) + (test[,2] > 3)>0)

の結果は下記になります。

   col1    col2     Or     Add
1  TRUE    TRUE   TRUE    TRUE
2    NA      NA     NA      NA
3 FALSE      NA     NA      NA
4 FALSE    TRUE   TRUE    TRUE
5    NA    TRUE   TRUE      NA
6  TRUE      NA   TRUE      NA

こちらでは、5行目や6行目のように、
NA | TRUE = TRUE
となってしまいますが、これはこれで良いこともあります。
(どちらかでもTRUEならもう片方がNAでも良い)
加法を使うことで厳密な結果を返すようにもできます(4列目)。

結論

NAを多く含むデータでは &は使わない。|は状況次第
と心がけています。*1

*1:ちなみに全く別の話ですがSASの場合はMissing valueをマイナス無限大として扱います。if x<0でMissing valueも釣れます。これも戸惑います。