子集化data.frame中的NA会出现意外情况

时间:2009-11-20 21:31:13

标签: r

请考虑以下代码。当您未在条件中明确测试NA时,该代码将在稍后的某个日期失败,然后您的数据会发生变化。

>   # A toy example
>   a <- as.data.frame(cbind(col1=c(1,2,3,4),col2=c(2,NA,2,3),col3=c(1,2,3,4),col4=c(4,3,2,1)))
>   a
  col1 col2 col3 col4
1    1    2    1    4
2    2   NA    2    3
3    3    2    3    2
4    4    3    4    1
>   
>   # Bummer, there's an NA in my condition
>   a$col2==2
[1]  TRUE    NA  TRUE FALSE
> 
>   # Why is this a good thing to do?
>   # It NA'd the whole row, and kept it
>   a[a$col2==2,]
   col1 col2 col3 col4
1     1    2    1    4
NA   NA   NA   NA   NA
3     3    2    3    2
>   
>   # Yes, this is the right way to do it
>   a[!is.na(a$col2) & a$col2==2,]
  col1 col2 col3 col4
1    1    2    1    4
3    3    2    3    2
>     
>   # Subset seems designed to avoid this problem
>   subset(a, col2 == 2)
  col1 col2 col3 col4
1    1    2    1    4
3    3    2    3    2

有人可以解释为什么没有is.na检查的行为会变得好或有用吗?

1 个答案:

答案 0 :(得分:30)

我绝对同意这不直观(I made that point before on SO)。为了防御R,我认为知道何时有缺失值是有用的(即这不是错误)。 ==运算符明确设计为通知用户NA或NaN值。有关更多信息,请参阅?“==”。它声明:

  

缺少值('NA')和'NaN'值被视为        即使对自己也不具有可比性,因此需要进行比较        总会产生'NA'。

换句话说,使用二元运算符(因为它是未知的),缺失值是不可比较的。

超越is.na(),你也可以这样做:

which(a$col2==2) # tests explicitly for TRUE

或者

a$col2 %in% 2 # only checks for 2

%in%定义为使用match()函数:

'"%in%" <- function(x, table) match(x, table, nomatch = 0) > 0'

"The R Inferno"也涵盖了这一点。

在R中检查数据中的NA值至关重要,因为许多重要的操作符都没有按照您的预期处理它。除了==之外,对于诸如&amp;,|,&lt;,sum()之类的东西也是如此。当我写R代码时,我总是在想“如果在这里有一个NA会发生什么”。要求R用户小心缺少值是“按设计”。

更新:当存在多个逻辑条件时,如何处理NA?

NA是一个逻辑常量,如果您不考虑可能返回的内容(例如NA | TRUE == TRUE),则可能会出现意外的子集。来自?Logic的这些真值表可以提供有用的说明:

outer(x, x, "&") ## AND table
#       <NA> FALSE  TRUE
#<NA>     NA FALSE    NA
#FALSE FALSE FALSE FALSE
#TRUE     NA FALSE  TRUE

outer(x, x, "|") ## OR  table
#      <NA> FALSE TRUE
#<NA>    NA    NA TRUE
#FALSE   NA FALSE TRUE
#TRUE  TRUE  TRUE TRUE