Supprimer une colonne nommée si et seulement si toutes les valeurs sont NA


rornornas

Je développe un package et j'ai des problèmes lorsque je souhaite supprimer une colonne nommée all-NA sans supprimer d'autres colonnes qui sont également all-NA.

Voici un exemple de bloc de données. Dans cet exemple, nous avons deux colonnes entièrement NA et cela est attendu et correct.

library(tidyverse)

df <- tribble(
  ~a,       ~b,    ~c,         ~d, ~AR, ~BR,
  1L, "animal", "dog",         NA,  NA,  NA,
  2L, "animal", "cat",         NA,  NA,  NA,
  3L, "animal", "rat",         NA,  NA,  NA,
  4L,  "plant", "oak", "carvalho",  NA,  NA
) %>% 
  mutate_if(is.logical, as.character)

df
#> # A tibble: 4 x 6
#>       a b      c     d        AR    BR   
#>   <int> <chr>  <chr> <chr>    <chr> <chr>
#> 1     1 animal dog   <NA>     <NA>  <NA> 
#> 2     2 animal cat   <NA>     <NA>  <NA> 
#> 3     3 animal rat   <NA>     <NA>  <NA> 
#> 4     4 plant  oak   carvalho <NA>  <NA>

Créé le 2020-02-06 par le package reprex (v0.3.0)

Cependant, supposons que je filtre la colonne bpour ne montrer que les animaux. Dans ce cas , nous aurions trois colonnes tout NA: d, ARet BR.

df %>% 
  filter(b == "animal")

df
#> # A tibble: 3 x 6
#>       a b      c     d     AR    BR   
#>   <int> <chr>  <chr> <chr> <chr> <chr>
#> 1     1 animal dog   <NA>  <NA>  <NA> 
#> 2     2 animal cat   <NA>  <NA>  <NA> 
#> 3     3 animal rat   <NA>  <NA>  <NA>

Créé le 2020-02-06 par le package reprex (v0.3.0)

Dans la fonction que je développe, je veux que dans le cas ci-dessus, quand dest tout-NA, il est supprimé mais aucune autre colonne tout-NA n'est pas supprimée. Donc, juste un select(-d)ne fonctionne pas car cela supprimerait totalement la colonne d, même si elle avait du contenu.

J'ai déjà essayé tidyr::drop_na, purrr::discardet dplyr::select_if- en conjonction avec, all(is.na())mais sans succès, abandonner uniquement la colonne d. Je suis à la recherche d'un moyen qui fonctionne de préférence avec des tuyaux. La seule façon de faire cela est de ne pas utiliser de pipe:if(all(is.na(df$d))) df$d <- NULL

ÉDITER:

Le résultat que j'attends est une fonction qui, lorsque je l'exécute dans le df d'origine, renvoie exactement le même df que l'original:

df
#> # A tibble: 4 x 6
#>       a b      c     d        AR    BR   
#>   <int> <chr>  <chr> <chr>    <chr> <chr>
#> 1     1 animal dog   <NA>     <NA>  <NA> 
#> 2     2 animal cat   <NA>     <NA>  <NA> 
#> 3     3 animal rat   <NA>     <NA>  <NA> 
#> 4     4 plant  oak   carvalho <NA>  <NA>

Mais dans la colonne de cas dest tout-NA, j'attends ce qui suit en retour:

df
#> # A tibble: 3 x 5
#>       a b      c     AR    BR   
#>   <int> <chr>  <chr> <chr> <chr>
#> 1     1 animal dog   <NA>  <NA> 
#> 2     2 animal cat   <NA>  <NA> 
#> 3     3 animal rat   <NA>  <NA> 
27 ϕ 9

Vous pouvez utiliser select_if()et tester les conditions avec %in%(dans le cas de plusieurs variables) pour les noms de colonne et en colSums()comptant les valeurs non-na.

df %>%
  filter(b == 'animal') %>%
  select_if(!names(.) %in% "d" | colSums(!is.na(.)) > 0)

# A tibble: 3 x 5
      a b      c     AR    BR   
  <int> <chr>  <chr> <chr> <chr>
1     1 animal dog   NA    NA   
2     2 animal cat   NA    NA   
3     3 animal rat   NA    NA  


df %>%
  select_if(!names(.) %in% "d" | colSums(!is.na(.)) > 0)

# A tibble: 4 x 6
      a b      c     d        AR    BR   
  <int> <chr>  <chr> <chr>    <chr> <chr>
1     1 animal dog   NA       NA    NA   
2     2 animal cat   NA       NA    NA   
3     3 animal rat   NA       NA    NA   
4     4 plant  oak   carvalho NA    NA   

Articles connexes