Je souhaite utiliser dplyr::mutate()
pour créer plusieurs nouvelles colonnes dans un bloc de données. Les noms de colonnes et leur contenu doivent être générés dynamiquement.
Exemple de données d'iris:
library(dplyr)
iris <- tbl_df(iris)
J'ai créé une fonction pour muter mes nouvelles colonnes à partir de la Petal.Width
variable:
multipetal <- function(df, n) {
varname <- paste("petal", n , sep=".")
df <- mutate(df, varname = Petal.Width * n) ## problem arises here
df
}
Maintenant, je crée une boucle pour construire mes colonnes:
for(i in 2:5) {
iris <- multipetal(df=iris, n=i)
}
Cependant, comme mutate pense que varname est un nom de variable littéral, la boucle ne crée qu'une nouvelle variable (appelée varname) au lieu de quatre (appelée petal.2 - petal.5).
Comment puis-je mutate()
utiliser mon nom dynamique comme nom de variable?
dplyr
a une vignette entière sur l'évaluation non standardmutate_
, et les autres fonctions ne savent pas vraiment comment l'utiliser.Réponses:
Puisque vous construisez dynamiquement un nom de variable en tant que valeur de caractère, il est plus judicieux de faire une affectation en utilisant l'indexation data.frame standard qui permet des valeurs de caractère pour les noms de colonne. Par exemple:
La
mutate
fonction permet de nommer très facilement de nouvelles colonnes via des paramètres nommés. Mais cela suppose que vous connaissez le nom lorsque vous tapez la commande. Si vous souhaitez spécifier dynamiquement le nom de la colonne, vous devez également créer l'argument nommé.version de dplyr> = 0.7
La dernière version de
dplyr
(0.7) le fait en utilisant:=
pour attribuer dynamiquement des noms de paramètres. Vous pouvez écrire votre fonction comme suit:Pour plus d'informations, consultez le formulaire de documentation disponible
vignette("programming", "dplyr")
.dplyr (> = 0,3 et <0,7)
Une version légèrement antérieure de
dplyr
(> = 0,3 <0,7), encourageait l'utilisation d'alternatives «d'évaluation standard» à de nombreuses fonctions. Consultez la vignette d'évaluation non standard pour plus d'informations (vignette("nse")
).Alors ici, la réponse est d'utiliser
mutate_()
plutôt que demutate()
faire:dplyr <0,3
Notez que cela est également possible dans les anciennes versions de celles
dplyr
qui existaient lorsque la question a été initialement posée. Cela nécessite une utilisation prudente dequote
etsetName
:la source
do.call()
ne fait probablement pas ce que vous pensez qu'il fait: rpubs.com/hadley/do-call2 . Voir aussi la vignette nse dans la version dev de dplyr.do.call
précède pour utiliserdo.call("mutate")
et citerdf
dans la liste. Est-ce ce que vous proposiez? Et quand lalazyeval
version dedplyr
est la version publiée, alorsmutate_(df, .dots= setNames(list(~Petal.Width * n), varname))
serait une meilleure solution?mutate(df, !!newVar := (!!var1 + !!var2) / 2)
ne fonctionne pas :(Dans la nouvelle version de
dplyr
(en0.6.0
attente d'avril 2017), nous pouvons également faire une affectation (:=
) et passer des variables en tant que noms de colonnes en unquoting (!!
) pour ne pas l'évaluerVérification de la sortie basée sur @ MrFlick
multipetal
appliqué sur 'iris1'la source
Après de nombreux essais et erreurs, j'ai trouvé le modèle
UQ(rlang::sym("some string here")))
vraiment utile pour travailler avec des chaînes et des verbes dplyr. Cela semble fonctionner dans de nombreuses situations surprenantes.Voici un exemple avec
mutate
. Nous voulons créer une fonction qui ajoute deux colonnes, où vous passez la fonction les deux noms de colonne sous forme de chaînes. Nous pouvons utiliser ce modèle, avec l'opérateur d'affectation:=
, pour ce faire.Le modèle fonctionne également avec d'autres
dplyr
fonctions. Voicifilter
:Ou
arrange
:Pour
select
, vous n'avez pas besoin d'utiliser le modèle. Au lieu de cela, vous pouvez utiliser!!
:la source
myCol
en une URL (par exemple), et copie l'ancienne colonnemyColInitialValue
à la fin du dataframedf
avec un nouveau nom. Maiswhich(colnames(df)=='myCol')
renvoyer le col # demyColInitialValue
. Je n'ai pas encore écrit de numéro car je n'ai pas trouvé de reprex. Mon objectif est pour leescape
paramètre deDT::datatable()
. J'utiliseescape=FALSE
en attendant ça. Avec les constantes, cela ne fonctionne pas non plus, mais le package DT semble également avoir la mauvaise colonne #. :)escape
unDT::datatable
varname = sym("Petal.Width"); ggplot(iris, aes(x=!!varname)) + geom_histogram()
Voici une autre version, et c'est sans doute un peu plus simple.
la source
Avec
rlang 0.4.0
nous avons des opérateurs bouclés ({{}}
) qui rendent cela très facile.Nous pouvons également passer des noms de variables entre guillemets / non guillemets à attribuer comme noms de colonne.
Cela fonctionne de la même manière avec
la source
J'ajoute également une réponse qui augmente un peu cela parce que je suis venu à cette entrée lors de la recherche d'une réponse, et cela avait presque ce dont j'avais besoin, mais j'avais besoin d'un peu plus, ce que j'ai obtenu via la réponse de @MrFlik et le R vignettes paresseux.
Je voulais créer une fonction qui pourrait prendre un dataframe et un vecteur de noms de colonnes (sous forme de chaînes) que je souhaite convertir d'une chaîne en objet Date. Je ne pouvais pas comprendre comment
as.Date()
prendre un argument qui est une chaîne et le convertir en colonne, alors je l'ai fait comme indiqué ci-dessous.Voici comment j'ai fait cela via SE mutate (
mutate_()
) et l'.dots
argument. Les critiques qui améliorent la situation sont les bienvenues.la source
Bien que j'aime utiliser dplyr pour une utilisation interactive, je trouve extrêmement difficile de le faire avec dplyr car vous devez passer par des obstacles pour utiliser lazyeval :: interp (), setNames, etc.
Voici une version plus simple utilisant la base R, dans laquelle il me semble plus intuitif, du moins pour moi, de mettre la boucle à l'intérieur de la fonction, et qui étend la solution de @ MrFlicks.
la source
dplyr
beaucoup dans des paramètres non interactifs, son utilisation avec une entrée variabel dans une fonction utilise une syntaxe très maladroite.Vous pouvez profiter du package
friendlyeval
qui présente une API eval simplifiée et une documentation pour lesdplyr
utilisateurs débutants / occasionnels .Vous créez des chaînes que vous souhaitez
mutate
traiter comme des noms de colonnes. Donc, en utilisant,friendlyeval
vous pourriez écrire:Ce qui sous le capot appelle des
rlang
fonctions qui vérifientvarname
est légal comme nom de colonne.friendlyeval
Le code peut être converti à tout moment en code eval simple équivalent avec un addin RStudio.la source
Autre alternative: utilisez des
{}
guillemets pour créer facilement des noms dynamiques. C'est similaire à d'autres solutions mais pas exactement les mêmes, et je trouve cela plus facile.Je pense que cela vient
dplyr 1.0.0
mais pas sûr (je l'ai aussirlang 4.7.0
si cela compte).la source