2017-09-14 85 views
2

我曾经在一个复杂的语句跨越dplyr::filter的行为无意中发现了一个的大数据帧,这基本上可以归结为治疗NA值:否定过滤条件给出与直觉相反的结果

df <- tibble(a = c(rep(1,3), 
       rep(NA, 3))) 

A tibble: 6 x 1 
     a 
    <dbl> 
1  1 
2  1 
3  1 
4 NA 
5 NA 
6 NA 

过滤对于等于行1给出了预期的结果:

df %>% filter(a == 1) 

A tibble: 3 x 1 
     a 
    <dbl> 
1  1 
2  1 
3  1 

滤波行不等于1,我希望要返回的其余3行的东风,然而这是不是这样的,:

df %>% filter(!a == 1) 

A tibble: 0 x 1 
... with 1 variables: a <dbl> 

因此,尽管在第一种情况下NA被解释为不等于1,在第二种情况下,它被解释为等于1。有我在这里失踪逻辑?

我知道我可以使用%in%来获得期望的结果:

df %>% filter(!a %in% 1) 

A tibble: 3 x 1 
     a 
    <dbl> 
1 NA 
2 NA 
3 NA 

但觉得奇怪,我使用该运营商只用一个元素(而不是矢量)。

所以我的问题给专家:这是filter的预期行为?否定过滤条件时,通常使用%in%吗?

回答

4

这是由于%in%而不是filter的行为。

让我们用一个简单的例子:

a = c(1, 1, 1, NA, NA, NA) 

> a == 1 
[1] TRUE TRUE TRUE NA NA NA 
> a != 1 
[1] FALSE FALSE FALSE NA NA NA 
> !(a == 1) 
[1] FALSE FALSE FALSE NA NA NA 

我们看到,当我们使用关系运算符==!=,NA的输入值保持在NA的输出。然而...

> a %in% 1 
[1] TRUE TRUE TRUE FALSE FALSE FALSE 
> !(a %in% 1) 
[1] FALSE FALSE FALSE TRUE TRUE TRUE 

随着%in%操作,在输入NA值成为输出FALSE。由于这被认为是为match()更直观的界面,让我们来看看这个还有:

> match(a, 1) 
[1] 1 1 1 NA NA NA 

所以没了,match()本身不行为这种方式,至少不使用默认参数。但是,帮助文件?match解释说:

%in%目前被定义为
"%in%" <- function(x, table) match(x, table, nomatch = 0) > 0

有你有它。当我们使用a %in% 1,我们实际上做了以下内容:

> match(a, 1, nomatch = 0L) 
[1] 1 1 1 0 0 0 

> match(a, 1, nomatch = 0L) > 0L 
[1] TRUE TRUE TRUE FALSE FALSE FALSE 

因此,当%in%运营商与!否定一起使用filter()回报与NA行的值。

+0

好吧,我明白了。所以反直觉行为(至少对我来说)是'=='在数据值为'NA'时产生'NA'。我宁愿期望'a == 1'与'NA'数据产生'FALSE',因为'NA'不等于1.我必须记住在这种否定条件下使用'%in%'。感谢您的回答! – user3460194

相关问题