2015-10-02 2 views
10

Когда я использую filter из пакета dplyr, чтобы понизить уровень факторной переменной, filter также снижает значения NA. Вот пример:Почему фильтр dplyr оставляет значения NA из переменной фактора?

library(dplyr) 
set.seed(919) 
(dat <- data.frame(var1 = factor(sample(c(1:3, NA), size = 10, replace = T)))) 
# var1 
# 1 <NA> 
# 2  3 
# 3  3 
# 4  1 
# 5  1 
# 6 <NA> 
# 7  2 
# 8  2 
# 9 <NA> 
# 10 1 

filter(dat, var1 != 1) 
# var1 
# 1 3 
# 2 3 
# 3 2 
# 4 2 

Это не кажется идеальным - я только хотел бросить строки, где var1 == 1.

Похоже, что это происходит потому, что любой comparison with NA returns NA, который затем падает filter. Так, например, filter(dat, !(var1 %in% 1)) дает правильные результаты. Но есть ли способ сказать filter, чтобы не уронить значения NA?

+2

@akrun По какой-то причине я не получил это уведомление: P. Ну, я думал, что OP уже знает об этом, поскольку он упомянул «фильтр (dat,! (Var1% in% 1))», который похож, но я думаю, что это был бы единственный способ сделать это с помощью 'dplyr :: filter'. – LyzandeR

+1

Я не думаю, что есть способ явно сказать 'filter' не отбрасывать значения NA, но в общем случае логические запросы NA могут быть интуитивно обработаны с использованием базового оператора'% in% 'и это отрицание, определяемое как' % ni% <- Negate ('% in%') '. Таким образом, вы можете использовать 'filter (dat, var1% ni% 1)', который будет работать. См. Http://stackoverflow.com/a/11303276/4269699 и http://stackoverflow.com/a/27015823/4269699 – wjchulme

+1

Да, я знал об этом и в подходе, который @LyzandeR использовал для ответа , Похоже, что у фильтра нет явного варианта «keep NA», поэтому эти обходные пути будут в порядке. Спасибо за вашу помощь. –

ответ

14

Вы могли бы использовать это:

filter(dat, var1 != 1 | is.na(var1)) 
    var1 
1 <NA> 
2 3 
3 3 
4 <NA> 
5 2 
6 2 
7 <NA> 

И это не будет.

Кроме того, только для завершения, сбросив NAs является намеченная поведение filter как вы можете видеть из следующего:

test_that("filter discards NA", { 
    temp <- data.frame(
    i = 1:5, 
    x = c(NA, 1L, 1L, 0L, 0L) 
) 
    res <- filter(temp, x == 1) 
    expect_equal(nrow(res), 2L) 
}) 

Этот тест выше был взят из испытаний для filter от github.

+2

Взявшись немного на территорию, основанную на мнениях, есть ли у вас идея, почему это выбранный подход? Такое поведение было неожиданным для меня (сегодня я его укусил). – Heisenberg

+1

@Heisenberg Я предполагаю, что согласно Хэдли большинство людей хотели бы, чтобы ни при каких фильтрах не получалось. Но это вопрос для разработчика/сопровождающего, то есть Хэдли. – LyzandeR