2 votes

R : Transformer un vecteur en une liste d'arguments

Je voudrais appliquer une fonction à un vecteur. Cependant, la fonction attend une séquence d'arguments. J'ai donc besoin de "diviser" le vecteur en arguments non liés.

Supposons que j'ai un cadre de données appelé dta . Je veux exécuter une fonction, disons moyenne sur une de ses colonnes, disons DV.

Le problème est le suivant

call("mean", dta$DV)

renvoie à

mean(c(0.371, -0.860, etc... ))

Le fait que la colonne soit un vecteur n'est pas compatible avec la fonction moyenne qui s'attend à une séquence d'arguments, non combinés.

La solution devrait fonctionner si "mean" est remplacé par une variable contenant une chaîne de caractères, par ex.

fun <- "mean"

call( fun, dta$DV)

2voto

r2evans Points 1187

R a des fonctions qui ne sont pas complètement cohérentes. Par exemple, min y max accepter un nombre arbitraire d'arguments, où tous les arguments non reconnus sont pris en compte dans le calcul mathématique. mean ne l'est pas, il doit avoir tous les numéros pour être considéré comme le premier (ou nommé) x= ).

min(1,20,0)
# [1] 0
min(c(1,20,0))
# [1] 0
mean(1,20,0) # might not be what one would expect
# [1] 1
mean(c(1,20,0))
# [1] 7

Pour les curieux, le 20 et le 0 ne sont pas ignorés, le premier mean est interprété comme mean(0, trim=20, na.rm=0) (où na.rm=0 est effectivement la même chose que na.rm=FALSE ).

Votre utilisation de call est un peu décalé. De l'aide ?call ,

call renvoie un appel de fonction non évalué

ce qui ne vous aide pas beaucoup. Vous pourriez faire eval(call(...)) mais cela semble idiot à la lumière de la fonction suivante.

Utilisation de do.call est un peu plus simple. Elle peut prendre comme premier argument : une fonction (anonyme ou nommée) ou une chaîne de caractères qui correspond à une fonction. Il y a en fait des différences de vitesse entre l'utilisation de l'une ou l'autre, donc j'ai tendance à utiliser une fonction character référence au nom de la fonction lorsque cela est possible. (Je ne me souviens pas de la référence qui quantifie cette affirmation, je l'inclurai si je la trouve bientôt).

Pour des fonctions comme min au-dessus qui peut accepter un nombre quelconque d'arguments, on peut faire ceci :

args <- c(1,20,0)

as.list(args)
# [[1]]
# [1] 1
# [[2]]
# [1] 20
# [[3]]
# [1] 0
do.call("min", as.list(args)) # == min(1,20,0)
# [1] 0

list(args)
# [[1]]
# [1]  1 20  0
do.call("min", list(args)) # == min(c(1,20,0))
# [1] 0

Toutefois, pour mean et similaires, vous devez forcer ce dernier comportement :

do.call("mean", list(args)) # == mean(c(1,20,0))
# [1] 7

Pour appeler une fonction avec des arguments définis de manière programmatique, vous devez utiliser do.call .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X