Comment utiliser R points de suspension en fonction lors de l'écriture de votre propre fonction?
Le langage R est une fonctionnalité utile pour définir des fonctions qui peuvent prendre un nombre variable d'arguments. Par exemple, la fonction data.frame
prend un nombre quelconque d'arguments, et chaque argument devient les données d'une colonne dans la table de données. Exemple d'utilisation:
> data.frame(letters=c("a", "b", "c"), numbers=c(1,2,3), notes=c("do", "re", "mi"))
letters numbers notes
1 a 1 do
2 b 2 re
3 c 3 mi
La fonction de signature comprend les points de suspension, comme ceci:
function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE,
stringsAsFactors = default.stringsAsFactors())
{
[FUNCTION DEFINITION HERE]
}
Je voudrais écrire une fonction qui fait la même chose, en prenant plusieurs valeurs et de les regrouper en une seule valeur de retour (ainsi que d'autres de traitement). Pour ce faire, j'ai besoin de comprendre comment faire pour "décompresser" le ...
de les arguments de la fonction au sein de la fonction. Je ne sais pas comment faire. La ligne correspondante dans la définition de la fonction de data.frame
est object <- as.list(substitute(list(...)))[-1L]
, que je ne peux pas donner un sens.
Alors, comment puis-je convertir le bouton de sélection de la fonction de signature, par exemple, dans une liste?
Pour être plus précis, comment puis-je écrire get_list_from_ellipsis
dans le code ci-dessous?
my_ellipsis_function(...) {
input_list <- get_list_from_ellipsis(...)
output_list <- lapply(X=input_list, FUN=do_something_interesting)
return(output_list)
}
my_ellipsis_function(a=1:10,b=11:20,c=21:30)
Modifier
Il semble qu'il y a deux façons de le faire. Ils sont as.list(substitute(list(...)))[-1L]
et list(...)
. Cependant, ces deux ne fait pas exactement la même chose. (Pour les différences, voir les exemples dans les réponses.) Quelqu'un peut-il me dire quelle est la différence concrète entre eux, et avec qui je devrais utiliser?
Vous devez vous connecter pour publier un commentaire.
J'ai lu les réponses et les commentaires et je vois que quelques choses n'ont pas été mentionnés:
data.frame
utiliselist(...)
version. Fragment de code:object
est utilisé pour faire de la magie avec les noms de colonnes, maisx
est utilisé pour créer finaldata.frame
.Pour l'utilisation de non évaluée
...
argument regarderwrite.csv
code oùmatch.call
est utilisé.Comme vous l'écrivez en commentaire suite à Dirk réponse n'est pas une liste de listes. Est une liste de longueur 4, les éléments qui sont
language
type. Premier objet est unsymbol
-list
, la seconde est l'expression1:10
et ainsi de suite. Ce qui expliquerait pourquoi[-1L]
est nécessaire: il supprime devraitsymbol
d'arguments fournis dans...
(car il est toujours dans une liste).Comme Dirk états
substitute
renvoie "arbre d'analyse de la non évaluée expression".Lorsque vous appelez
my_ellipsis_function(a=1:10,b=11:20,c=21:30)
puis...
"crée" une liste d'arguments:list(a=1:10,b=11:20,c=21:30)
etsubstitute
faire une liste de quatre éléments:Premier élément n'ont pas de nom et c'est
[[1]]
Dirk réponse. Je parvenir les résultats à l'aide:Comme ci-dessus, nous pouvons utiliser
str
de vérifier ce que les objets sont dans une fonction.C'est ok. Permet de voir
substitute
version:N'est pas ce dont nous avions besoin. Vous aurez besoin de plus d'astuces pour faire face à ces types d'objets (comme dans
write.csv
).Si vous souhaitez utiliser
...
alors vous devriez l'utiliser comme Shane réponse, parlist(...)
.Vous pouvez convertir les points de suspension dans une liste avec
list()
et effectuez vos opérations:De sorte que votre
get_list_from_ellipsis
fonction est rien de plus quelist
.Valide d'un cas d'utilisation de ce est dans le cas où vous souhaitez passer dans un nombre indéterminé d'objets pour l'opération (comme dans votre exemple de
c()
oudata.frame()
). Ce n'est pas une bonne idée d'utiliser le...
quand vous savez que chaque paramètre à l'avance, cependant, car il ajoute une certaine ambiguïté, et d'autre complication de la chaîne d'argument (et fait de la signature de la fonction claire pour tout autre utilisateur). La liste d'arguments est une pièce importante de la documentation de la fonction des utilisateurs.Sinon, il est également utile pour les cas où vous souhaitez passer des paramètres à un sous-fonction sans s'exposer à tous dans vos propres arguments de la fonction. Cette information peut être indiquée dans la documentation des fonctions.
list
etc
fonctions fonctionnent de cette façon, mais les deux sont primitives, donc je ne peux pas facilement inspecter le code source pour comprendre comment ils fonctionnent.rbind.data.frame
utiliser de cette façon.list(...)
est suffisante, pourquoi faire R les builtins commedata.frame
utiliser la forme longueas.list(substitute(list(...)))[-1L]
à la place?data.frame
, je ne connais pas la réponse à ça (cela dit, je suis sûr qu'il y a est une bonne raison pour cela). J'utiliselist()
à cet effet dans mes paquets et n'avons pas encore rencontré un problème avec elle.Juste pour ajouter à Shane et Dirk réponses: il est intéressant de comparer
avec
Comme il est, soit la version s'affiche adaptés à vos besoins dans
my_ellipsis_function
, si le premier est clairement plus simple.Vous a donné la moitié de la réponse déjà. Envisager
Si cela a pris deux arguments
a
etb
à partir de l'appel et l'a converti en une liste. N'était-ce pas ce que vous avez demandé?[[1]]
. Aussi, je voudrais savoir comment l'incantation magiqueas.list(substitute(list(...)))
œuvres.list(...)
crée unlist
objet basé sur les arguments. Puissubstitute()
crée l'arbre d'analyse pour les non évaluée expression; consultez l'aide de cette fonction. Ainsi qu'un bon de texte avancé sur R (ou S). Ce n'est pas anodin des trucs.[[-1L]]
partie (à partir de ma question)? Ne devrait-elle pas être[[1]]
?print(c(1:3)[-1])
imprime 2 et 3 seulement. LeL
est d'un nouveau genre pour que cela se termine comme un entier, cela se fait beaucoup dans la R sources.[[1]]
et la$a
indices m'a fait penser que des listes imbriquées ont été impliqués. Mais maintenant je vois que ce que vous obtenez est la liste que je veux, mais avec un élément supplémentaire à l'avant. Alors la[-1L]
de sens. Où est-ce que supplémentaires premier élément de venir, de toute façon? Et est-il une raison je devrais utiliser ce lieu de simplementlist(...)
?Cela fonctionne comme prévu.
La suite est une session interactive:
Même, sauf avec un argument par défaut:
Comme vous pouvez le voir, vous pouvez l'utiliser pour passer des "extra" les arguments d'une fonction au sein de votre fonction si les valeurs par défaut ne sont pas ce que vous voulez dans un cas particulier.