R 拆分“…”参数并分配到多个函数

R 拆分“…”参数并分配到多个函数,r,R,使用下面的函数foo()作为一个简单的例子,如果可能的话,我想将中给出的值分配到两个不同的函数中 foo <- function(x, y, ...) { list(sum = sum(x, ...), grep = grep("abc", y, ...)) } 参数似乎是先发送到grep()的。对吗?我认为R会首先看到并计算sum(),然后返回一个错误 此外,在尝试拆分…中的参数时,我遇到了麻烦sum()的形式参数为NULL,因为它是原语,因此无法使用 names(formal

使用下面的函数
foo()
作为一个简单的例子,如果可能的话,我想将
中给出的值分配到两个不同的函数中

foo <- function(x, y, ...) {
    list(sum = sum(x, ...), grep = grep("abc", y, ...))
}
参数似乎是先发送到
grep()
的。对吗?我认为R会首先看到并计算
sum()
,然后返回一个错误

此外,在尝试拆分
中的参数时,我遇到了麻烦
sum()
的形式参数为
NULL
,因为它是
原语,因此无法使用

names(formals(sum)) %in% names(list(...))
我也不想假设

names(formals(grep)) %in% names(list(...))
将自动传递给
sum()

如何安全有效地将
..
参数分配给多个函数,以便不进行不必要的计算?

从长远来看,我希望能够将此应用于具有一长串
..
参数的函数,类似于
download.file()
scan()
的函数

  • 为什么
    grep
    sum
    之前出错

    请注意,
    sum
    对其参数更为适应:

    X <- c(1:5, NA, 6:10)
    sum(X, na.rm = TRUE, value = TRUE)
    ## [1] 56
    
  • 如何将
    拆分为不同的函数

    一种方法(很容易出错)是查找目标函数的参数。例如:

    foo <- function(x, y, ...){
        argnames <- names(list(...))
        sumargs <- intersect(argnames, names(as.list(args(sum))))
        grepargs <- intersect(argnames, names(as.list(args(grep))))
        list(sum = do.call(sum, c(list(x), list(...)[sumargs])),
             grep = do.call(grep, c(list("abc", y), list(...)[grepargs])))
    }
    
    在这种情况下,您可以替换适当的S3函数。因此,我没有一个通用的解决方案(尽管我不知道它是否存在)


  • 如果另一个函数包含传递给
    ..
    的所有命名参数,或者该函数本身具有
    ..
    参数,则只能将
    ..
    参数传递给另一个函数。因此,对于
    sum
    ,这没有问题(
    args(sum)
    返回
    函数(…,na.rm=FALSE)
    )。另一方面,
    grep
    既没有
    na.rm
    也没有
    ..
    作为参数

    args(grep)
    # function (pattern, x, ignore.case = FALSE, perl = FALSE, value = FALSE, 
    #     fixed = FALSE, useBytes = FALSE, invert = FALSE) 
    
    这不包括
    ,也不包括命名参数
    na.rm
    。一个简单的解决方案是只定义自己的函数
    mygrep
    ,如下所示:

    mygrep <- function (pattern, x, ignore.case = FALSE, perl = FALSE, value = FALSE, 
                        fixed = FALSE, useBytes = FALSE, invert = FALSE, ...)
      grep(pattern, x, ignore.case, perl, value, fixed, useBytes, invert)
    

    mygrep独立列表如果您真的想将不同的参数集传递给不同的函数,那么指定独立列表可能更为简洁:

    foo <- function(x, y, sum = list(), grep = list()) {
     list(sum = do.call("sum", c(x, sum)), grep = do.call("grep", c("abc", y, grep)))
    }
    
    # test
    
    X <- c(1:5, NA, 6:10)
    Y <- "xyzabcxyz"
    foo(X, Y, sum = list(na.rm = TRUE), grep = list(value = TRUE))
    
    ## $sum
    ## [1] 55
    ## 
    ## $grep
    ## [1] "xyzabcxyz"
    
    ii)
    nls
    也使用
    ..
    控件
    列表采用这种方法:

    > args(mapply)
    function (FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE) 
    NULL
    
    > args(nls)
    function (formula, data = parent.frame(), start, control = nls.control(), 
        algorithm = c("default", "plinear", "port"), trace = FALSE, 
        subset, weights, na.action, model = FALSE, lower = -Inf, 
        upper = Inf, ...) 
    NULL
    

    将完全相同的
    值发送到两个函数
    sum(X,na.rm=TRUE,value=TRUE)
    不会返回错误(注意
    sum(1,na.rm=TRUE,value=TRUE)==2
    ),但是
    grep(“abc”,Y,na.rm=TRUE,value=TRUE)
    会根据函数实际使用的内容更改
    。如果你想分割参数,你必须自己做。另一种方法是为所有非常用参数提供默认值。一般来说,尝试将省略号args发送到多个地方会导致悲伤。我认为一种更干净、更健壮的方法是避免
    对所有内部函数或其中一个内部函数以外的所有函数使用
    do.call
    foo=function(x,y,sum_args=list(NULL),grep_args=list(NULL))list(sum=do.call(“sum”,c(list(x),sum_args)),grep=do.call(“grep”,c(list(“abc”),list(y),grep_args))
    <代码>foo(c(1:5,NA,6:10),“xyzabcxyz”)
    foo(c(1:5,NA,6:10),“xyzabcxyz”,sum_args=list(NA.rm=TRUE),grep_args=list(value=TRUE))
    @alexis_laz是的,我说的是:-)。非常详细。对于基本函数,您可以使用例如
    formals(args(sum))
    来检索参数。第一句话不对-您可以传递
    ,即使其他函数不接受
    。例如:
    add@wch:感谢您指出这一点。相应地修改了第一句。第一段仍然具有误导性
    
    foo <- function(x, y, ...){
      list(sum = sum(x, ...), grep = mygrep("abc", y, ...))
    }
    X <- c(1:5, NA, 6:10)
    Y <- "xyzabcxyz"
    foo(X, Y, na.rm = TRUE, value = TRUE)
    
    # $sum
    # [1] 56
    # 
    # $grep
    # [1] "xyzabcxyz"
    
    foo <- function(x, y, sum = list(), grep = list()) {
     list(sum = do.call("sum", c(x, sum)), grep = do.call("grep", c("abc", y, grep)))
    }
    
    # test
    
    X <- c(1:5, NA, 6:10)
    Y <- "xyzabcxyz"
    foo(X, Y, sum = list(na.rm = TRUE), grep = list(value = TRUE))
    
    ## $sum
    ## [1] 55
    ## 
    ## $grep
    ## [1] "xyzabcxyz"
    
    foo <- function(x, y, sum = list(), ...) {
     list(sum = do.call("sum", c(x, sum)), grep = grep("abc", y, ...))
    }
    
    foo(X, Y, sum = list(na.rm = TRUE), value = TRUE)
    
    > args(mapply)
    function (FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE) 
    NULL
    
    > args(nls)
    function (formula, data = parent.frame(), start, control = nls.control(), 
        algorithm = c("default", "plinear", "port"), trace = FALSE, 
        subset, weights, na.action, model = FALSE, lower = -Inf, 
        upper = Inf, ...) 
    NULL