【问题标题】:Pass arguments in nested function to update default arguments在嵌套函数中传递参数以更新默认参数
【发布时间】:2016-02-23 20:13:41
【问题描述】:

我有嵌套函数并希望将参数传递给最深的函数。最深的函数已经有默认参数,所以我将更新这些参数值。

我的 mwe 使用的是 plot(),但实际上我使用的是 png(),带有默认的高度和宽度参数。

有什么建议吗?

f1 <- function(...){ f2(...)}

f2 <- function(...){ f3(...)}

f3 <- function(...){ plot(xlab="hello1", ...)}

#this works
f1(x=1:10,y=rnorm(10),type='b')

# I want to update the default xlab value, but it fails:
f1(x=1:10,y=rnorm(10),type='b', xlab='hello2')

【问题讨论】:

  • f3 &lt;- function(myxlab = 'hello1', ...) { plot(xlab = myxlab, ...) } 呢?

标签: r arguments


【解决方案1】:

在您的f3() 中,"hello1" 不是函数形式参数列表中xlab 的默认值。相反,它是函数体中提供的值,因此无法覆盖它:

f3 <- function(...){ plot(xlab="hello1", ...)}

我怀疑你的意思是做这样的事情。

f1 <- function(...){ f2(...)}
f2 <- function(...){ f3(...)}
f3 <- function(..., xlab="hello1") plot(..., xlab=xlab)

## Then check that it works
par(mfcol=c(1,2))
f1(x=1:10,y=rnorm(10),type='b')
f1(x=1:10,y=rnorm(10),type='b', xlab='hello2')

(请注意,形式参数xlab 必须跟在...参数后面,这样它就只能完全匹配(而不是部分匹配)。否则,在没有对于名为xlab 的参数,它将与名为x 的参数匹配,可能(实际上在这里)给你带来很多悲伤。)

【讨论】:

  • 谢谢乔希。我认为这是一个简单的解决方案。
  • @mfolkes 当然,很高兴为您提供帮助。
【解决方案2】:

我在...中修改参数的常用方法如下:

f1 = function(...) {
  dots = list(...)
  if (!('ylab' %in% names(dots))) {
    dots$ylab = 'hello'
  }
  do.call(plot, dots)
}
# check results 
f1(x = 1:10, y = rnorm(10)) 
f1(x = 1:10, y = rnorm(10), ylab = 'hi') 

这里发生的是... 被捕获在一个名为dots 的列表中。接下来,R 检查此列表dots 是否包含有关ylab 的任何信息。如果没有信息,我们将其设置为指定值。如果有信息,我们什么也不做。最后,do.call(a, b) 是一个基本上支持带有参数b 的voor 执行函数b 的函数。

编辑

使用多个默认参数时效果更好(通常也可能更好)。

f1 = function(...) {
  # capture ... in a list
  dots = list(...)
  # default arguments with their values
  def.vals = list(bty = 'n', xlab = 'hello', las = 1)
  # find elements in dots by names of def.vals. store those that are NULL
  ind = unlist(lapply(dots[names(def.vals)], is.null))
  # fill empty elements with default values 
  dots[names(def.vals)[ind]] = def.vals[ind]
  # do plot
  do.call(plot, dots)
}

f1(x = 1:10, y = rnorm(10), ylab = 'hi', bty = 'l') 

【讨论】:

  • 这真的很有帮助。但我想如果我要更新多个默认参数,我需要为每个参数设置一个if(){}
  • 哇,那个编辑添加是......非常令人印象深刻。我会把它放在我的后口袋里。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-03
  • 1970-01-01
  • 2014-02-27
  • 1970-01-01
  • 2020-07-29
  • 1970-01-01
  • 2016-12-14
相关资源
最近更新 更多