== で NA と比較すると NA が返り FALSE にはならない
NAを含む式を==で比較すると、結果はTRUEでもFALSEでもなくNAになります。「等しくない」ことを確認したいつもりでNAと比較しても、判定自体ができません。
エラーメッセージの読み方
Error in if (value == 5) { : missing value where TRUE/FALSE needed
Error- エラー種別 — 実行中に発生しました
if (value == 5) {- 発生箇所 — エラーの原因になった呼び出し
missing value where TRUE/FALSE needed- 詳細メッセージ — 何が問題だったか
このエラーが出る典型パターン
パターン1
1 value <- NA 2 if (value == 5 ) { ^ 3 cat("skip\n") 4 } else { 5 cat("process\n") 6 }
NAとの==比較はTRUEでもFALSEでもなくNAになるため、if()の条件に使うとその場でエラーになります。
直し方: value == 5 を is.na(value) にします。
パターン2
1 age <- NA 2 if (age == 20 ) { ^ 3 cat("skip\n") 4 } else { 5 cat("process\n") 6 }
ageがNAのとき==での比較結果もNAになるので、is.na()で先に確認する必要があります。
直し方: age == 20 を is.na(age) にします。
パターン3
1 score <- NA 2 if (score == 0 ) { ^ 3 cat("skip\n") 4 } else { 5 cat("process\n") 6 }
scoreがNAの場合、0と比較してもFALSEにはならずNAになるため、if()はエラーで止まります。
直し方: score == 0 を is.na(score) にします。
パターン4
1 status <- NA 2 if (status == "done") { ^ 3 cat("skip\n") 4 } else { 5 cat("process\n") 6 }
文字列との比較でも、statusがNAであれば結果はNAになり、if()の条件としては使えません。
直し方: status == "done" を is.na(status) にします。
パターン5
1 flag <- NA 2 if (flag == TRUE) { ^ 3 cat("skip\n") 4 } else { 5 cat("process\n") 6 }
論理値同士の比較でも、片方がNAならば==の結果はNAになり、if()には使えません。
直し方: flag == TRUE を is.na(flag) にします。
よくある誤解
「NAと比較すればFALSEになって、if文で安全に弾けるはず」という思い込みは誤りです。NAとの比較結果は常にNAで、if()の条件に使うとエラーになります。NAかどうかを調べたい場合はis.na()を使う必要があります。
実務での勘所
同じ「値が含まれているか」を調べる操作でも、%in%は==と違ってNAを賢く扱います。NA %in% c(1, 2, NA)はTRUEになり、NA %in% c(1, 2, 3)はFALSEになります。%in%は常に明確なTRUE/FALSEを返し、NAを1つの特別な値として律儀に照合してくれるためです。「NAが含まれているかどうか」を調べたいだけなら、==で比較してNAが返ってくることに悩むより、is.na()や%in%を使うほうが素直に答えが得られます。