web-dev-qa-db-ja.com

R関数の入力引数の存在を確認する方法

次のように定義された関数があります

_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(...)
}
_

この関数で、引数リストにユーザーが「z」を入力したかどうかを確認したいと思います。どうやってやるの?私はexists("z")missing("z")get("z")を試しましたが、どれも機能しません。

34
danioyuan

@Sacha Epskampにはかなり良い解決策がありますが、常に機能するとは限りません。失敗するのは、 "z"引数が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

あなたは単にhasArgを探していると思います

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

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

?hasArg

たとえば、式hasArg(x)は!missing(x)に似ていますが、2つの例外があります。まず、hasArgは、xが呼び出し元の関数の正式な引数ではないが...である場合、呼び出しでxという引数を探します。次に、名前が引数として指定されている場合、hasArgはエラーを生成しませんが、xが仮引数でない場合、missing(x)はエラーを生成します。

60
GSee

list(...)を呼び出したくない場合があります。これは、ドット内のすべての式を評価するためです。例えば、

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

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

これには時間がかかります。代わりに、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)))
_

最初の例は私のマシンでまだぎこちないですが、2番目の例はほとんど時間がかかりません。

編集:

@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

これが私がよく行う方法です。最初に変換...をリストに追加し、要素がNULLではないかどうかを確認します。

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

いくつかの結果:

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