【问题标题】:How to check existence of an input argument for R functions如何检查 R 函数的输入参数是否存在
【发布时间】:2012-04-10 06:14:50
【问题描述】:

我有一个函数定义为

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"),但它们都不起作用。

【问题讨论】:

  • 你能具体说明你是如何使用missing的吗?因为 AFAIK 是正确使用的函数。
  • 如果您提供更多背景信息会有所帮助。可能有更好的方法来完成您想要完成的工作。
  • @joran, missing() 仅适用于参数。这里没有参数z,只能作为...的一部分输入
  • @SachaEpskamp 我同意。我只是不确定 OP 写的是否真的是他们在做的。
  • 我已经修改了问题中的代码,使其更易于理解。感谢 cmets。

标签: r function arguments exists


【解决方案1】:

我认为您只是在寻找hasArg

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

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

来自?hasArg

例如,表达式 hasArg(x) 类似于 !missing(x),具有 两个例外。首先,hasArg 将在 如果 x 不是调用函数的正式参数,则调用,但是... 是。其次,如果将名称作为 参数,而如果 x 不是正式的,missing(x) 会生成错误 论据。

【讨论】:

    【解决方案2】:

    @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
    

    【讨论】:

      【解决方案3】:

      在某些情况下,您可能不想调用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)))
      

      第一个示例仍在我的机器上运行,而第二个示例几乎不需要任何时间。

      编辑:

      回答@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
      

      【讨论】:

      • 为了完整起见,您能否报告一下它确实运行第二个示例所需的时间?
      • 嗨@CarlWitthoft,请看我上面的编辑。你得到不同的结果吗?
      • 好吧,我的结果是 NULL,因为我(还)不允许在工作中安装 R :-(。所以,感谢您进行计时测试。
      【解决方案4】:

      这是我经常这样做的一种方式。先将...转换为列表,然后检查元素是否不是NULL

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

      一些结果:

      > myFun()
      [1] FALSE
      > myFun(z=1)
      [1] TRUE
      

      【讨论】:

      • 我不认为这是 ... 应该使用的预期方式。它更像是一种将参数传递给另一个函数的方式,但这也是我目前在我的包中使用它的方式(我真的应该改变它:))
      • 萨莎,我同意你的看法。如果在这个函数中使用了“z”,那么它不应该出现在 ... 但是很多时候代码已经编写好了,在参数列表中进行一次更改可能会引入需要进行多次更改才能修复的错误。所以这是我让它工作的懒惰方式。 :)
      • 我添加了一个替代解决方案,它也可以处理myFun(z=NULL)
      • @danioyuan 这也为您提供了只有您知道的令人敬畏的隐藏和无证论点!
      • @danioyuan:添加参数的安全且可能“正确”的方法是将其放在列表的最后并分配默认值,即 myfunc(x,y,...) 变为 myfunc(x,y,z=1,...) 。 AFAIK 将提供完全的向后兼容性。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-18
      • 2015-07-24
      • 2020-06-01
      • 2011-09-22
      相关资源
      最近更新 更多