Supprimer une colonne nommée si et seulement si toutes les valeurs sont NA
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 b
pour ne montrer que les animaux. Dans ce cas , nous aurions trois colonnes tout NA: d
, AR
et 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 d
est 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::discard
et 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 d
est 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>
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