函数参数依赖于默认参数

问题描述 投票:2回答:3

我正在尝试编写一个在R中有默认参数的函数。最后一个参数告诉我用户如何计算变量'g'。默认值为“s + a”(前两个参数的总和),但原则上它可以由任何函数指定(例如“s - a”或“s * a”......)。

myFunc <- function(n, 
                   s = rbernoulli(n, p = 0.5), 
                   a = rnorm(n,sd = 2),2),
                   g = s + a){
      data.frame(s = factor(s),
                 a = a,
                 g = as.numeric(g>0))
}

如果我调用函数本身,这可以正常工作:

myFunc(5)

要指定我想要'g'的计算方式,我想这样做:

myFunc(n = 5, g = a - s) (I)

要么

myFunc(n = 5, a = ., s = ., g = a - s) (II)

似乎(I)将导致R在工作空间中查找变量s / a,这不是我想要的。并且(II)不存在,但是我的方式是“使用默认计算”。

我尝试用NULL指定我的函数,但这也不起作用。请注意,我希望能够在我的值之后在函数中使用'g'(所以我不能用函数代替它)。

r function parameter-passing
3个回答
2
投票

我认为最好的方法是使g成为一个接受两个参数的函数,sa。然后,您可以在需要时传递不同的功能:

myFunc <- function(n,
                   s = purrr::rbernoulli(n, p = 0.5),
                   a = rnorm(n, sd = 2),
                   g = function(s, a) { s + a }) {
    g_val = g(s, a)
    data.frame(s = factor(s),
               a = a,
               g = as.numeric(g_val > 0))
}

myFunc(5)
myFunc(5, g = function(s, a) { s - a })

3
投票

问题是g在调用环境中进行评估,而不是在myFunc中的环境中进行评估。您可以添加一个参数来指定评估g的环境,并使用默认值environment(),以便它默认为myFunc2中的环境。

myFunc2 <- function(n, 
                   s = rbernoulli(n, p = 0.5), 
                   a = rnorm(n,sd = 2),
                   g,
                   envir = environment()) {
      g <- if (missing(g)) s + a else eval(substitute(g), envir)
      data.frame(s = factor(s),
                 a = a,
                 g = as.numeric(g>0))
}
myFunc2(n = 5, g = s + a)

2
投票

这可以使用非标准评估来完成。有许多方法可以实施。我现在大多使用quosures和rlang::eval_tidy。以下是使用此函数实现的函数:

library(purrr)
library(rlang)
myFunc <- function(
  n, 
  s = rbernoulli(n, p = 0.5), 
  a = rnorm(n, sd = 2),
  g = s + a) {
  if (!missing(g)) {
    g <- eval_tidy(enquo(g), list(s = s, a = a))
  }
  data.frame(s = factor(s),
             a = a,
             g = as.numeric(g>0))
}

这将使用您建议的示例myFunc(n = 5, g = a - s)。如果未提供g参数,则默认为在其他参数的上下文中评估默认表达式的标准r功能。

另请注意,这适用于quasiquotation,因此您可以执行以下操作:

my_expr <- expr(a - s)
myFunc(n = 5, g = !!my_expr)

couple of有非标准评估的great chapters Hadley Wickham's Advanced R

仅使用基数R(您提供的purrrr:bernoulli除外):

library(purrr)
myFunc <- function(
  n, 
  s = rbernoulli(n, p = 0.5), 
  a = rnorm(n, sd = 2),
  g = s + a) {
  if (!missing(g)) {
    g <- eval(substitute(g), list(s = s, a = a))
  }
  data.frame(s = factor(s),
             a = a,
             g = as.numeric(g>0))
}
© www.soinside.com 2019 - 2024. All rights reserved.