2017-09-14 57 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