web-dev-qa-db-fra.com

Utilisation des fonctions de plusieurs colonnes dans un appel dplyr mutate_at

J'aimerais utiliser la fonction mutate_at De dplyr pour appliquer une fonction à plusieurs colonnes dans un cadre de données, la fonction saisissant la colonne à laquelle elle est directement appliquée ainsi qu'une autre colonne du cadre de données.

Comme exemple concret, je chercherais à muter le dataframe suivant

# Example input dataframe
df <- data.frame(
    x = c(TRUE, TRUE, FALSE),
    y = c("Hello", "Hola", "Ciao"),
    z = c("World", "ao", "HaOlam")
)

avec un appel mutate_at semblable à celui-ci

df %>%
mutate_at(.vars = vars(y, z),
          .funs = ifelse(x, ., NA))

renvoyer une image de données qui ressemble à ceci

# Desired output dataframe
df2 <- data.frame(x = c(TRUE, TRUE, FALSE),
                  y_1 = c("Hello", "Hola", NA),
                  z_1 = c("World", "ao", NA))

L’appel souhaité mutate_at Serait similaire à l’appel suivant à mutate:

df %>%
   mutate(y_1 = ifelse(x, y, NA),
          z_1 = ifelse(x, z, NA))

Je sais que cela peut être fait en base R de plusieurs manières, mais je voudrais spécifiquement atteindre cet objectif en utilisant la fonction mutate_at De dplyr pour des raisons de lisibilité, d'interfaçage avec des bases de données, etc.

Ci-dessous se trouvent quelques questions similaires posées sur stackoverflow qui ne répondent pas à la question que j'ai posée ici:

ajout de plusieurs colonnes dans un appel dplyr mutate

dplyr :: mutate pour ajouter plusieurs valeurs

tilisation de la colonne dans la fonction sum () à l'aide de la fonction mutate () de dplyr

41
bschneidr

@ Eipi10 a répondu à cela dans le commentaire de @ eipi10 sur la question, mais je l'écris ici pour la postérité.

La solution ici est d'utiliser:

df %>%
   mutate_at(.vars = vars(y, z),
             .funs = list(~ ifelse(x, ., NA)))

L'utilisation de list(~ ...) indique ici que ifelse(x, ., NA) est une fonction anonyme définie dans l'appel à mutate_at().

Cela fonctionne de la même manière pour définir la fonction en dehors de l'appel à mutate_at(), comme ceci:

temp_fn <- function(input) ifelse(test = df[["x"]],
                                  yes = input,
                                  no = NA)

df %>%
   mutate_at(.vars = vars(y, z),
             .funs = temp_fn)

Note sur les changements de syntaxe dans dplyr: Avant dplyr version 0.8.0, vous écririez simplement .funs = funs(ifelse(x, . , NA)), mais la fonction funs() est obsolète et sera bientôt être retiré de dplyr.

50
bschneidr

Pour compléter la réponse précédente, si vous vouliez que mutate_at() ajoute de nouvelles variables (au lieu de les remplacer), avec des noms tels que z_1 Et y_1 Comme dans la question initiale, vous venez besoin d'ajouter le nom dans l'appel funs(newname= ...):

df %>%
  mutate_at(.vars = vars(y, z),
            .funs = funs(`1`=ifelse(x, ., NA)))

Cela donne:

# A tibble: 3 x 5
  x     y     z      y_1   z_1  
  <lgl> <chr> <chr>  <chr> <chr>
1 TRUE  Hello World  Hello World
2 TRUE  Hola  ao     Hola  ao   
3 FALSE Ciao  HaOlam NA    NA   

Pour plus de détails et d’astuces, voir: Créer de nouvelles variables avec mutate_at tout en conservant les variables originales

8
Matifou