2015-10-02 13 views
10

Quando si utilizza filter dal pacchetto dplyr per eliminare un livello di una variabile fattore, filter rilascia anche i valori NA. Ecco un esempio:Perché il filtro di dplyr rilascia valori NA da una variabile fattore?

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 

Questo non sembra l'ideale - volevo solo far cadere righe in cui var1 == 1.

Sembra che questo si verifichi perché qualsiasi comparison with NA returns NA, che quindi filter scende. Ad esempio, filter(dat, !(var1 %in% 1)) produce i risultati corretti. Ma c'è un modo per dire a filter di non lasciare cadere i valori NA?

+2

@akrun Per qualche motivo non ho ricevuto questa notifica: P. Bene, ho pensato che l'OP già lo sa, come ha menzionato 'filter (dat,! (Var1% in% 1))' che è simile, ma penso che questo sarebbe l'unico modo per farlo con 'dplyr :: filter'. – LyzandeR

+1

Non penso ci sia un modo per dire esplicitamente a 'filter' di non rilasciare i valori di' NA', ma in generale, le query logiche di NA possono essere gestite intuitivamente usando l'operatore di base '% in%' e la sua negazione, definita come ' % ni% <- Negate ('% in%') '. Quindi, potresti usare 'filter (dat, var1% ni% 1)' che funzionerà. Vedere http://stackoverflow.com/a/11303276/4269699 e http://stackoverflow.com/a/27015823/4269699 – wjchulme

+1

Sì, conoscevo sia questo approccio sia l'approccio che @LyzandeR usava per una risposta . Sembra che il filtro non abbia un'opzione esplicita per "mantieni NA", quindi queste soluzioni alternative andranno bene. Grazie per l'aiuto. –

risposta

14

È possibile utilizzare questo:

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

E non lo farà.

Anche solo per il completamento, lasciando cadere NAS è il comportamento previsto del filter come si può vedere dalla seguente:

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) 
}) 

Questa prova di cui sopra è stata presa dalle prove per filter da github.

+2

Avventurarsi un po 'nel territorio basato sull'opinione pubblica, hai un'idea del perché questo è l'approccio scelto? Questo comportamento era inaspettato per me (sono stato morso da oggi). – Heisenberg

+1

@Heisenberg Suppongo che, secondo Hadley, la maggior parte della gente vorrebbe non ottenere alcun NA durante il filtraggio. Ma questa è una domanda per lo sviluppatore/manutentore, ad esempio Hadley. – LyzandeR