我正在尝试编写一个函数,该函数在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”(例如,我不能用函数代替它)。
答案 0 :(得分: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)
答案 1 :(得分:2)
我认为最好的方法是使g
一个接受两个参数s
和a
的函数。然后,您可以在需要时传递其他功能:
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 })
答案 2 :(得分:2)
这可以使用非标准评估来完成。有多种方法可以实现此目的。我现在主要使用quasure和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功能,即在其他参数的上下文中评估默认表达式。
请注意,这也可以使用准引号,因此您可以执行以下操作:
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))
}