我在通过递归调用integrate
函数传递参数时遇到麻烦。这是一个简单的例子,说明了我的难题。
考虑一个函数foo1
,该函数需要参数x
并返回x
的某些转换。例如:
foo1 = function(x, alpha = 1.5) {
return(x^alpha)
}
现在考虑一个函数foo2
,它也需要x
并返回一些不同的转换:
foo2 = function(x, y, z) {
return(x * y * z)
}
现在考虑一个函数bar
,该函数返回任何类似x
的函数的有限积分(从xMax
到foo
),但是接受一个多个值的向量x
:
bar = function(xVals, xMax, ..., fun) {
return(
sapply(
xVals,
function(xVal) integrate(f = fun, lower = xVal, upper = xMax, ...)$value)
)
}
请注意,foo1
的参数alpha
将作为...
的一部分传递:
bar(10:20, 100, alpha = 1.5, fun = foo1)
和foo2
的参数y
和z
也将作为...
的一部分传递:
bar(10:20, 100, y = 2, z = 4, fun = foo2)
我喜欢这种安排,因为integrate
的其他必需参数也可以作为...
的一部分传递。例如,要更改subdivisions
调用的integrate
函数的bar
参数的默认值,只需指定:
bar(10:20, 100, y = 2, z = 4, fun = foo2, subdivisions = 200L)
现在,考虑一个将bar
从xStart集成到xEnd,但接受xStart和xEnd的多个值的向量的函数。可能看起来像这样:
integrateBar = function(xStart, xEnd, xMax, ..., fun) {
aMatrix = cbind(xStart, xEnd)
result =
apply(
aMatrix,
1,
function(xRange) integrate(bar, xRange[1], xRange[2], xMax, ..., fun = fun)$value
)
return(result)
}
所以这很好并且很简单,直到我想调用integrateBar
,但要为subdivisions
中调用的integrate
函数更改bar
参数的值。如果我使用:
integrateBar(10:20, 40, 100, alpha = 1.5, subdivisions = 200L, fun = foo1)
subdivisions
参数由integrate
中的integrateBar
函数捕获和使用,并且不传递给bar
。这是理想的行为-有时。但是有时我也希望能够将subdivisions
中integrate
调用的integrateBar
保留为默认设置,而将integrate
中bar
的调用更改为默认设置。有人可以告诉我一种优雅的方法吗?
我愿意为bar
修改形式,但我也不想让它过于笨拙,因为我也想直接调用bar
。如果有一些R技巧,那么subdivisions
参数将被遇到的第一个集成函数忽略,但对第二个集成函数可用,将是非常好的。
我最好的解决方法是为integrate
编写一个使用参数SUBDIVISIONS
的包装器,然后从bar
调用包装器。如果没有更好的答案,我将发布该解决方案。
答案 0 :(得分:1)
参数subdivisions
不会从integrate
传递,因为它是integrate
的实际命名参数(仅...
中的参数)将传递给f:
> integrate
# function (f, lower, upper, ..., subdivisions = 100L, rel.tol = .Machine$double.eps^0.25,
# abs.tol = rel.tol, stop.on.error = TRUE, keep.xy = FALSE,
# aux = NULL)
一种不需要更改bar
的可能解决方案是在bar
内为integrateBar
写一个包装。我有两种变体:
变种1:
如果要将...
中的参数传递给integrate
的外部调用和内部调用,那就是这样:
integrateBar = function(xStart, xEnd, xMax, ..., fun) {
argsExtra <- list(...)
# A wrapper function for bar:
# Note that the argument ... is necessary, although the function does not use
# it. This is because, we still pass ... to the call to integrate below.
CallBarOnFun <- function(xVals, xMax, ...) {
do.call(bar, c(list(xVals, xMax), argsExtra, list(fun=fun)))
}
aMatrix = cbind(xStart, xEnd)
result =
apply(
aMatrix,
1,
function(xRange) {
integrate(CallBarOnFun, xRange[1], xRange[2], xMax, ...)$value
}
)
return(result)
}
变体2:如果仅要将...
中的参数传递给内部调用:
integrateBar = function(xStart, xEnd, xMax, ..., fun) {
argsExtra <- list(...)
CallBarOnFun <- function(xVals, xMax) {
do.call(bar, c(list(xVals, xMax), argsExtra, list(fun=fun)))
}
aMatrix = cbind(xStart, xEnd)
result =
apply(
aMatrix,
1,
function(xRange) {
integrate(CallBarOnFun, xRange[1], xRange[2], xMax)$value
}
)
return(result)
}