【问题标题】:How to overwrite a hardcoded function argument with the dots (...) parameter?如何用点 (...) 参数覆盖硬编码的函数参数?
【发布时间】:2019-10-15 22:44:33
【问题描述】:

我正在尝试使用一组默认值以及通过使用 plot 函数在点 (...) 参数中接受的任何参数来更改这些值的灵活性来创建一个绘图函数。一个例子:

PlotIt <- function(x, y, ...) {
  plot(x, y, type = "l", asp = 1, ...)
}

x <- 1:10
y <- 10:1

PlotIt(x = x, y = y)
# Returns a plot
PlotIt(x = x, y = y, asp = NA)
# Error in plot.default(x, y, type = "l", asp = 1, ...) : 
#  formal argument "asp" matched by multiple actual arguments

错误自然是因为我尝试将asp参数两次传递给plot。到目前为止,我最好的笨拙尝试是做一个 if-else 语句来考虑这一点(该方法是从 here 修改的):

PlotIt2 <- function(x, y, ...) {

  mc <- match.call(expand.dots = FALSE)

  if(names(mc$...) %in% "asp") {
  plot(x, y, type = "l", ...)  
  } else {
  plot(x, y, type = "l", asp = 1, ...)  
  }

}

PlotIt2(x = x, y = y, asp = NA)
# works

要使用... 参数设置所有可能的参数,我需要编写一个很长的if-else 语句。 有更优雅的方法吗?

问题与this one 有关,不同之处在于我想自动覆盖... 参数设置的所有参数。

【问题讨论】:

    标签: r


    【解决方案1】:

    如果您只想使用基础 R, 您可以将所有内容放在列表中并根据参数名称删除重复项 (确保默认值位于最后,以便在 ... 中存在它们时将其删除):

    PlotIt <- function(x, y, ...) {
      arguments <- list(
        x = x,
        y = y,
        ...,
        type = "l",
        asp = 1
      )
    
      arguments <- arguments[!duplicated(names(arguments))]
    
      do.call("plot", arguments)
    }
    

    如果您不介意依赖rlang, 您还可以执行以下操作, 使用.homonyms 获得相同的功能 (并检查坐标轴的绘图标签, 基本 R 和 rlang 版本之间会有所不同):

    PlotIt <- function(x, y, ...) {
      require("rlang")
      arguments <- rlang::dots_list(
        rlang::expr(x),
        rlang::expr(y),
        ...,
        type = "l",
        asp = 1,
        .homonyms = "first"
      )
    
      call <- rlang::call2("plot", !!!arguments)
      eval(call)
    }
    

    【讨论】:

    • 您是否也可以在此示例中使用match.call() 来解决here 中描述的问题?我想了解match.call(),但我更喜欢你的方法,它更直观
    • @user63230 好吧,Mikko 在他的问题中尝试的是我能想到的,我不知道如何改进。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-26
    • 2013-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多