在R中一次检查所有函数参数的长度

时间:2018-01-06 00:49:05

标签: r function

作为一个完整性检查,我希望当下面的函数seda中的任何参数是长度大于1的向量时,函数会停止。

问题:而不是单独列出所有函数参数(此处为xyz),是否可以使用{{1} }或match.call等,以便可以立即检查所有函数参数?

我尝试了以下但没有成功:

formals

4 个答案:

答案 0 :(得分:2)

match.call()将捕获函数的参数,然后可以测试其长度。我们使用sapply返回一个带有每个函数参数长度的向量,并使用any函数来测试任何参数的长度是否大于1。

seda <- function(x, y, z){

  if(any(sapply(match.call()[-1], length) > 1)) stop("All arguments must be length 1")

  x + y + z
}

seda(2, 2, 3)
[1] 7
seda(c(2, 3), 2, 3)
Error in seda(c(2, 3), 2, 3) : All arguments must be length 1

感谢@erocoar指出可以使用match.call代替sys.call,而as.list是不必要的。

答案 1 :(得分:1)

你可以调整一下你可以使用的东西:

seda <- function(...){
    stopifnot(lengths(list(...)) == 1)

    sum(...)
}

seda(1, 1, 1)
#> [1] 3

seda(1, 1, 1:2)
#> Error: lengths(list(...)) == 1 are not all TRUE

...或使用命名参数

seda_named <- function(x, y, z){
    stopifnot(lengths(list(x, y, z)) == 1)

    x + y + z
}

seda_named(1, 1, 1)
#> [1] 3

seda_named(1, 1, 1:2)
#> Error: lengths(list(x, y, z)) == 1 are not all TRUE

要使用stop代替stopifnot以控制错误消息,请将条件包装在all中。

答案 2 :(得分:0)

如果一次性测试它们,则错误消息不会说明哪个参数是问题。下面在循环中对它们进行测试,并确实指出错误消息中哪个是有问题的参数。

seda <- function(x, y, z) {
  argnames <- names(match.call()[-1])
  for(nm in argnames) if (length(get(nm)) != 1) stop(nm, " does not have length 1")
  x + y + z
}

# test - note that the error message names z
seda(10, 20, 1:2)
## Error in seda(10, 20, 1:2) : z does not have length 1

当然,如果你真的有3个参数,那么将它写出来会简单得多。这也提供了参数特定的错误消息:

seda <- function(x, y = 1, z) {
  stopifnot(length(x) == 1, length(y) == 1, length(z) == 1)      
  x + y + z
}

seda(10, 20, 1:2)
## Error: length(z) == 1 is not TRUE

答案 3 :(得分:0)

我非常感谢我的专家同事的投入。使用您宝贵的意见,我想我想要的是以下内容:

seda <- function(x, y, z){

if(lengths(list(get(names(match.call()[-1])))) > 1) stop("Error")

 x + y + z
}

seda(c(2, 3), 2, 3) 
seda(2, 2, 3)

我们也可以使用formals

   seda <- function(x, y, z){

    if(lengths(list(get(names(formals(seda))))) > 1) stop("Error")
     x + y + z
     }

   seda(c(2, 3), 2, 3)
   seda(2, 2, 3)

formalArgs喜欢这样:

    seda <- function(x, y, z){

     if(lengths(list(get(formalArgs(seda)))) > 1) stop("Error")
       x + y + z
        }

       seda(c(2, 3), 2, 3)
       seda(2, 2, 3)