【问题标题】:Using multiple three dot ellipsis in R [duplicate]在R中使用多个三点省略号[重复]
【发布时间】:2017-06-19 20:19:26
【问题描述】:

有没有办法将任意参数传递给函数内的多个命令?以下功能显然不起作用,但我希望它能解释我想要实现的目标。

test = function(x = rnorm(20), y = rnorm(20), ..., ---){
    plot(x, y, type = "p", ...)
    lines(x, y, ---) 
}

我们的目标是能够编写一个函数来创建绘图,比如 linespointspolygon 并且可以为每个命令获取任意参数并将它们传递给相应的命令,而无需我明确指定每个命令的参数。

【问题讨论】:

  • 也许你能解释一下这样做的目的是什么。
  • R 如何知道将哪些参数传递给哪个函数?目前尚不清楚您希望它如何工作。这也可能与此重复:how to pass the “…” parameters in the parent function to its two children functions in r
  • 我认为您需要详细说明,可能使用比您在结束段落中的内容更具体的示例。我很确定您只需要创建一个包含“选项”的参数,然后将它们解析出来。例如,请参见 optimcontrol 参数。
  • 没有什么是不可能的*。如果您更全面地描述所需的行为,那将会很有帮助。显示您计划如何调用此函数。期望的输出是什么。 (*有一些限制)
  • 我的意思是,您需要展示一个如何使用该函数的示例(可能是几个示例,因为您正在尝试灵活的语法)以及预期的输出。

标签: r


【解决方案1】:

这是一种骇人听闻的方法:

.. <- "/////" #or anything which won't be used as a valid parameter

f <- function(...){
  arguments <- list(...)
  if(.. %in% arguments){
    i <- which(arguments == ..)
    terms <- unlist(arguments[1:(i-1)])
    factors <- unlist(arguments[(i+1):length(arguments)])
    c(sum(terms),prod(factors))
  }
}

然后,例如,

> f(2,3,4,..,7,8,10)
[1]   9 560

您显然可以将这个想法扩展到多个 ... 字段,每个字段以 .. 分隔

【讨论】:

    【解决方案2】:

    选项 1

    功能

    test = function(x = rnorm(20), y = rnorm(20), plot_options = NA, ...){
        if (is.na(plot_options) == FALSE){
            eval(parse(text = paste0("plot(x, y, ", plot_options, ")")))
        } else {
            plot(x, y, type = "n")
        }
        lines(x, y, ...) 
    }
    

    用法

    test()
    

    set.seed(42)
    m = rnorm(20)
    n = rnorm(20)
    test(x = m, y = n,
        plot_options = "type = 'p', col = 'red', pch = 19, xlab = 'Test Plot', ylab = 'Y-axis'")
    

    选项 2(@Gregor 的解决方案)

    功能

    test2 = function(x = rnorm(20), y = rnorm(20), ..., line_options){
        plot(x, y, ...)
        if (missing(line_options)) { 
            lines(x, y) 
        } else { 
            do.call(lines, c(list(x = x, y = y), line_options))
        }
    }
    

    用法

    par(mfrow = c(2, 2), mar = c(2, 2, 1, 1))
    test2(main = 'default')
    test2(line_options = list(lty = 2), main = 'line')
    test2(col = 'red', main = 'plot')
    test2(col = 'red', line_options = list(lty = 2, col = 'blue'), main = 'line and plot')
    

    【讨论】:

    • 关闭时我正在研究另一个答案(尽管我认为骗子很好)。您带有参数字符串的eval 似乎是不好的做法。 do.calllist 更好(就像在骗子中一样)。不幸的是plot 使用substitute 作为默认轴名称,这与do.call 不兼容。一个体面的解决方法是使用... 调用plot(),使用lines_options 列表调用lines
    • 试试这个:test2 = function(x = rnorm(20), y = rnorm(20), ..., line_options){ plot(x, y, ...); if (missing(line_options)) { lines(x, y) } else { do.call(lines, c(list(x = x, y = y), line_options)) } }
    • 使用示例:par(mfrow = c(2, 2), mar = c(2, 2, 1, 1)); test2(main = 'default'); test2(line_options = list(lty = 2), main = 'line'); test2(col = 'red', main = 'plot'); test2(col = 'red', line_options = list(lty = 2, col = 'blue'), main = 'line and plot'); 这样看起来更干净。
    猜你喜欢
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-01
    • 2017-01-21
    • 1970-01-01
    • 2011-04-16
    • 2018-07-30
    相关资源
    最近更新 更多