Dúvidas: dplyr::filter

Olá pessual,

Estou com uma dúvida no dplyr::filter. Fiz exemplinho com o banco starwars do dplyr. Veja que na variável hair_color temos NA e vamos supor que a contabilização desse NA é muito importante, mas eu não quero a categoria none. O meu interesse é fazer uma tabela de n(%) com o pacote qwraps2 (fica a dica) somente com as categorias especificadas no filter e também os NA.

Quando você for reproduzir veja que no filter da categoria none consequentemente o filter retira a categoria NA e eu não quero isso.

Já fiz com testes com código abaixo e a retirada de NA ainda continua:

dplyr::filter(hair_color == "blonde" | hair_color == "brown" | hair_color == "black" | hair_color == is.na(hair_color))

Exemplo:

library(qwraps2)
library(dplyr)

starwars %>% 
  dplyr::select(hair_color)  %>% 
  dplyr::filter(!(hair_color == "none")) %>% 
  dplyr::filter(hair_color == blonde | hair_color == "brown" | hair_color == "black" | hair_color == is.na(hair_color)) %>%  
  dplyr::summarise("blonde"      = qwraps2::n_perc(hair_color == "blonde", na_rm = TRUE, show_symbol = FALSE),
                   "brown"       = qwraps2::n_perc(hair_color == "brown", na_rm = TRUE, show_symbol = FALSE),
                   "black"       = qwraps2::n_perc(hair_color == "black", na_rm = TRUE, show_symbol = FALSE), 
                   "Missing"     = qwraps2::n_perc(is.na(hair_color), show_symbol = FALSE))  %>% 
  base::t()

Fernanda,

O seu problema é de fato bastante relevante. A função dplyr::filter() tem um comportamento específico: ela joga fora todas as linhas para as quais a condição tem o valor NA.

Note that when a condition evaluates to NA the row will be dropped, unlike base subsetting with [.

Veja o exemplo abaixo. Se considerarmos que a hair_color é NA, então a condição final também vira NA! A lógica aqui é que NA é um valor missing, ou seja, não sabemos se ele é diferente de “none” ou não… Então o resultado da condição também vai ser missing e acabará sendo jogado fora pelo dplyr::filter()!

# NA == X é sempre NA, independente de X
!(NA == "none")
#> [1] NA

Created on 2022-04-04 by the reprex package (v2.0.1)

O seu teste com o is.na() estava no caminho certo, o problema foi o hair_color ==. A função is.na() vai retornar TRUE se o valor de hair_color for NA, mas aí você está perguntando se hair_color é igual a esse resultado; NA == X é sempre NA (como vimos acima), então vamos quebrar o teste de volta. Veja o raciocínio abaixo:

# Queremos isso
is.na(NA)
#> [1] TRUE

# O `==` quebra o teste
NA == is.na(NA)
#> [1] NA

Created on 2022-04-04 by the reprex package (v2.0.1)

Sendo assim, o teste correto que queremos envolve tanto o is.na() quanto o == "none":

library(magrittr)

# TRUE | X é sempre TRUE, mesmo que X seja NA
is.na(NA) | !(NA == "none")
#> [1] TRUE

# Agora sim, veja o NA no final!
dplyr::starwars %>%
  dplyr::select(hair_color) %>%
  dplyr::filter(is.na(hair_color) | !(hair_color == "none")) %>%
  dplyr::count(hair_color) # Aqui iria o seu summarise()
#> # A tibble: 12 × 2
#>    hair_color        n
#>    <chr>         <int>
#>  1 auburn            1
#>  2 auburn, grey      1
#>  3 auburn, white     1
#>  4 black            13
#>  5 blond             3
#>  6 blonde            1
#>  7 brown            18
#>  8 brown, grey       1
#>  9 grey              1
#> 10 unknown           1
#> 11 white             4
#> 12 <NA>              5

Created on 2022-04-04 by the reprex package (v2.0.1)

1 Curtida

Não quis poluir a resposta, então vou fazer um adendo separado.

Veja que, apesar de !(X == Y) (“não X igual a Y”) funcionar, eu acho que é mais fácil pensar em X != Y (“X não igual a Y” ou “X diferente de Y”). Não usei != na minha resposta para não confundir, mas vou deixar aqui o capítulo sobre testes lógicos do nosso livro: 3.7 Testes lógicos | Ciência de Dados em R. Vale à pena dar uma olhada :slight_smile:

1 Curtida

Que SENSACIONAL Caio :grinning:! Faz total sentido isso aí. Muito obrigada!

1 Curtida