NA в подмножестве data.frame делает что-то неожиданное

Рассмотрим следующий код. Если вы явно не тестируете 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 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

Я определенно согласен с тем, что это не интуитивно (Я сделал этот пункт раньше на SO). В защиту R, я думаю, что знание, когда у вас отсутствует значение, полезно (т.е. Это не ошибка). Оператор == явно предназначен для уведомления пользователя о значениях NA или NaN. См.? "==" для получения дополнительной информации. В нем указано:

Отсутствующие значения ( "NA" ) и "NaN" считаются      несопоставимы даже с самими собой, поэтому сравнения с ними      всегда приведет к "NA".

Другими словами, недостающее значение не сопоставимо с использованием двоичного оператора (поскольку он неизвестен).

Beyond 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" .

Проверка значений NA в ваших данных имеет решающее значение для R, потому что многие важные операторы не справляются с этим так, как вы ожидаете. Beyond ==, это также верно для таких вещей, как &, |, <, sum() и т.д. Я всегда думаю "что будет, если бы здесь было NA", когда я пишу R-код. Требование, чтобы пользователь 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