我试图在R中编写一个函数,它接受两个函数(用一个可以被视为相同的参数定义的函数),将它们相乘,并返回在某个新点上求出的乘积的积分。现在,乘以函数并不难,这里的问题在于,与其计算参数x
中的一个函数,不如在w/x
中计算它,其中w
是新的参数(但我只想在函数产品中这样做)。这是我的代码:
"%*f%" <- function(a,b) {
force(a)
force(b)
function(x){a(x) * b(x)}
}
pdf_product <- function(pdf1, pdf2) {
pdf3 <- function(x,w) {pdf2(w/x)}
myfun <- function(x,w) {
(1/abs(x)) %*f% pdf1(x) %*f% pdf3(x,w)
}
function(w) {
sapply(w, function(w) {
integrate(function(x) myfun(x,w), llim, ulim)$value
})
}
}
pdf1 <- function(x) {1/(2-1)} #simple function example1
pdf2 <- function(x) {1/(6-3)} #simple function example2
llim <- 1 #lower limit integral
ulim <- 2 #upper limit integral
prod <- pdf_product(pdf1, pdf2)
prod(4) #should evaluate to 0.09589402
我知道pdf_product
的最后一部分正确工作,给定一个工作函数myfun
(因为这是二维函数上的单个积分在R中运行的方式,但是如果我错了,请纠正我)。但是,如果运行上述代码,将得到以下错误消息(带有回溯):
Error in integrate(function(x) myfun(x, w), llim, ulim) :
evaluation of function gave a result of wrong length
5.
integrate(function(x) myfun(x, w), llim, ulim)
4.
FUN(X[[i]], ...)
3.
lapply(X = X, FUN = FUN, ...)
2.
sapply(w, function(w) {
integrate(function(x) myfun(x, w), llim, ulim)$value
})
1.
prod(4)
我觉得这个错误与我通过从pdf3
定义pdf2
引入的“变量更改”有关,但我找不到修复它的方法。我试过在%*f%
返回的函数中使用著名的R三点原理,但这也不起作用。
发布于 2017-04-05 08:39:34
所以,您的问题是想要组成两个函数,但是这些函数可以有两个以上的参数。这可能是有用的:
"%*f%" <- function(a,b, ...) {
force(a)
force(b)
if (length(formals(args(a))) > 1L &&
length(formals(args(b))) > 1L)
stop("Only one function with additional parameters allowed.")
if (length(formals(args(a))) == 1L &&
length(formals(args(b))) > 1L)
return(function(x, ...){a(x) * b(x, ...)})
if (length(formals(args(a))) > 1L &&
length(formals(args(b))) == 1L)
return(function(x, ...){a(x, ...) * b(x)})
if (length(formals(args(a))) == 1L &&
length(formals(args(b))) == 1L)
return(function(x){a(x) * b(x)})
stop("Function without parameters passed")
}
(sign %*f% abs)(-5)
#[1] -5
(sign %*f% `+`)(-5, 1)
#[1] 4
请注意,如果两个函数都可以有多个参数,则需要设计一种传递这些参数的不同方法:
"%*f%" <- function(a,b, args1 = NULL, args2 = NULL) {
stopifnot(is.list(args1) | is.null(args1))
stopifnot(is.list(args2) | is.null(args2))
force(a)
force(b)
if (length(formals(args(a))) > 1L &&
length(formals(args(b))) > 1L)
return(function(x, args1, args2) do.call(a, c(x, args1)) * do.call(b, c(x, args2)))
#code for the other cases
}
(`^` %*f% `+`)(-5, list(2), list(1))
#[1] -100
如果你是管道爱好者的话,你最好考虑使用软件包magrittr。
https://stackoverflow.com/questions/43223173
复制相似问题