web-dev-qa-db-fra.com

Comment vérifier l'existence d'un argument d'entrée pour les fonctions R

J'ai une fonction définie comme

myFun <- function(x, y, ...) {
  # using exists
  if (exists("z")) { print("exists z!") }
  # using missing
  try(if (!missing("z")) { print("z is not missing!") }, silent = TRUE)
  # using get
  try(if (get("z")) { print("get z!") }, silent = TRUE)

  # anotherFun(...)
}

Dans cette fonction, je veux vérifier si l'entrée utilisateur "Z" dans la liste des arguments. Comment puis je faire ça? J'ai essayé exists("z"), missing("z") et get("z") et aucun d'entre eux ne fonctionne.

34
danioyuan

@Sacha Epskamp a une assez bonne solution, mais cela ne fonctionne pas toujours. Le cas où il échoue est si l'argument "Z" est transmis comme null ...

# Sacha's solution
myFun <- function(x, y, ...) { 
  args <- list(...)
  exist <- !is.null(args[['z']])
  return(exist)
}

myFun(x=3, z=NULL) # FALSE, but should be TRUE!


# My variant
myFun2 <- function(x, y, ...) {
  args <- list(...)
  exist <- "z" %in% names(args)
  exist
}

myFun2(x=3, z=NULL) # TRUE
30
Tommy

Je pense que vous recherchez simplement hasArg

myFun <- function(x, y, ...) { 
  hasArg(z)
}

> myFun(x=3, z=NULL)
[1] TRUE

De ?hasArg:

L'expression hatug (x), par exemple, est similaire à! (X) manquant, à deux exceptions près. Premièrement, Hasarg recherchera un argument nommé X dans l'appel si X n'est pas un argument formel à la fonction d'appel, mais ... est. Deuxièmement, Hasarg ne génère jamais une erreur si elle est donnée un nom comme un argument, alors que Manquant (x) génère une erreur si X n'est pas un argument formel.

60
GSee

Il pourrait y avoir des instances lorsque vous ne voudrez peut-être pas appeler list(...), car cela évaluera toutes les expressions des points. Par exemple,

myFun <- function(x, y, ...){
  myArgs <- list(...)
  zInArgs <- ("z" %in% names(myArgs))
  return(zInArgs)
}

myFun(x = 2, y = "Happy", z = list(rep(rnorm(2e6), 100)))

Cela prendra beaucoup de temps. Utilisez plutôt match.call():

myFun <- function(x, y, ...){
  myArgs <- match.call()
  zInArgs <- ("z" %in% names(myArgs))
  return(zInArgs)
}

myFun(x = 2, y = "Happy", z = list(rep(rnorm(2e6), 100)))

Le premier exemple est toujours en train de racler sur ma machine, tandis que le deuxième exemple ne doit prendre pratiquement pas de temps.

Edit :

Pour répondre au commentaire de @carlwitthoft:

R> system.time(
+   (myAns <- myFun(x = 2, y = "Happy", z = list(rep(rnorm(2e6), 100))))
+ )
   user  system elapsed 
      0       0       0 
R> myAns
[1] TRUE
8
BenBarnes

Voici une façon de le faire souvent. Première convertir ... à une liste, puis vérifiez si les éléments ne sont pas NULL:

myFun <- function(x, y, ...) { 
args <- list(...)
exist <- !is.null(args[['z']])
return(exist)
}

Quelques résultats:

> myFun()
[1] FALSE
> myFun(z=1)
[1] TRUE
4
Sacha Epskamp