【问题标题】:in R: turn list of functions into one big function (element-wise sum of functions)在 R 中:将函数列表变成一个大函数(函数的元素总和)
【发布时间】:2014-06-12 01:56:11
【问题描述】:

我有一个函数列表,我想将它们添加到一个“大”函数中。示例:

funlist=list()  
funlist[[1]]=exp(x1)
funlist[[2]]=sin(x2)

期望的结果:

bigfun = exp(x1) + sin(x2)

我知道数字情况可以使用reduce("+", list),但上述非数字情况呢?

请注意:我正在寻找一个通用的自动化解决方案,即函数列表可能会有所不同(函数本身和列表长度/函数数量),但列表的所有函数必须添加到一个最终术语到底。每个函数都应该有自己的必须提供的值(例如,x1 到 funlist[[1]],x2 到 funlist[[2]] 等)。

重要提示:然后将 bigfun 项传递给优化器 (optim) 以找到每个函数的最佳值,从而最大化所有函数的结果。

编辑: 为简单起见,我选择了函数 exp(x1) 和 sin(x2)。这些函数本身就是函数包装器,例如 function(x) {y1*x + y2*x^2 + y3*x^3} ,其中 y1, y2, y3 之前已经计算过。

【问题讨论】:

  • f <- function(x) sin(x) + exp(x) 然后例如f(0.5).
  • 感谢您的发帖,但不幸的是,这不是一个可应用于各种功能的通用解决方案(我进一步编辑了我的文字以使其更清晰)。
  • 是的,我看到了。在这种情况下,Bens 解决方案似乎适合我。希望这是你要找的。好问题顺便说一句。 +1。
  • 谢谢西蒙。 Ben 的想法朝着正确的方向发展,但还不是我想要的。
  • 请贴出优化问题。

标签: r list function


【解决方案1】:

这是一个函数,它将接受一个函数列表并返回一个计算它们总和的函数:

add.funs <- function(funlist) {
   function(...) Reduce(`+`, lapply(funlist, do.call, as.list(...)))
}

例如:

funlist=list()  
funlist[[1]] <- function(x) {5*x + 2*x^2 + 3*x^3}
funlist[[2]] <- function(x)sin(x)

bigfun <- add.funs(funlist)

bigfun(3)
# [1] 114.1411

这确实是一样的:

funlist[[1]](3) + funlist[[2]](3)
# [1] 114.1411

编辑:对于每个函数的单个不同参数,试试这个:

add.funs <- function(funlist) {
   function(...) {
      arglist <- lapply(as.list(...), as.list)
      Reduce(`+`, Map(do.call, funlist, arglist))
   }
}

bigfun <- add.funs(funlist)

bigfun(c(3, 4))
# [1] 113.2432
funlist[[1]](3) + funlist[[2]](4)
# [1] 113.2432

【讨论】:

  • 谢谢弗洛德尔。尚未测试此解决方案,因为我需要为每个函数提供不同的输入(我知道可以扩展您的方法,类似于 Ben 的嵌套函数)。因此,我接受了本的回答。
  • 我可以改进。您能否澄清一下:每个函数是否都采用一个不同的参数?
  • 是的,你是对的,每个函数都有一个不同的参数(x1、x2、..)。
  • +1。干得好弗洛德尔,谢谢!学到了一些新东西(MAP)。为了公平起见,我将 Ben 的答案保留为已接受的答案,因为他是第一个提供完整解决方案的人。
【解决方案2】:

这是一种函数式编程方法,您可以将函数存储在列表中。

funs <- c(sin,exp)

bigfun<-function(x,funs){
sum(sapply(funs, function(f) f(x)))}

bigfun(x=10,funs=funs)

从 Hadley Wickham 那里了解到: http://adv-r.had.co.nz/Functional-programming.html#lists-of-functions

**EDIT**提供多个值(即每个函数的不同值):

bigfun2<-function(vec,funs){vf<-function(vec,funs){funs(vec)} 
sum(sapply(1:length(vec),function (i) vf(vec[i],funs[[i]])))}

optim(par=initvec,fn=bigfun2,funs=funs)

这假设您有一个等于数据向量长度的函数列表,其中funs 是您的函数列表,vec 是您的数据向量。在优化示例中,只需将初始起始值等长的向量initvec 设置为funs,将其作为附加参数传递给optim

【讨论】:

  • 谢谢本。差不多了。但是,这不是要求所有功能都像乐趣一样吗?乐趣不能成为功能的一部分,因为它会有所不同。
  • 你可以很容易地让它成为 bigfun 的论点之一。一秒
  • 现在看看;您可以将函数存储在列表中,并将列表作为参数提供给bigfun
  • 嗨,本,感谢您的努力。我想我没有很好地解释这个问题(我编辑了我原来的问题)。虽然您可以将函数提供给函数包装器“bigfun”,但不应传递值(在您的示例中为“x”)(每个函数也应该有所不同)。我需要 bigfun 成为一个功能可泛化的术语(因为它用于优化)。如果这是有道理的。
  • 你想优化什么?您不必将固定数据向量传递给优化,您只需设置初始值
【解决方案3】:

另请参阅:

make_bigfun <- function(..., sep = " + ") {
   funlist = list(...)

   ff = function() NULL
   environment(ff) = parent.frame()

   formals(ff) = unlist(lapply(funlist, formals)) 
   body(ff) = parse(text = do.call(paste, c(lapply(funlist, function(x) deparse(body(x))), sep = sep)))

   return(ff)
}

make_bigfun(function(x1) exp(x1), function(x2) sin(x2), function(x3) cos(x3))
#function (x1, x2, x3) 
#exp(x1) + sin(x2) + cos(x3)
do.call(make_bigfun, c(list(function(x1) exp(x1), function(x2) sin(x2)), sep = " - "))
#function (x1, x2) 
#exp(x1) - sin(x2)
bigfun = make_bigfun(function(x1) exp(x1), function(x2) sin(x2))
identical(exp(1) + sin(2), bigfun(1,2))
#[1] TRUE

【讨论】:

    【解决方案4】:

    这样的事情怎么样:

    假设函数存储为字符串:

    funlist=list()  
    funlist[[1]]="exp(x)"
    funlist[[2]]="sin(x)"
    

    可以组合字符串,然后解析+eval:

    eval(parse(text=paste("bigfun <- function(x)", do.call(paste,c(funlist,sep="+")))))
    

    【讨论】:

      猜你喜欢
      • 2014-06-10
      • 1970-01-01
      • 2020-05-15
      • 1970-01-01
      • 2016-01-21
      • 1970-01-01
      • 2020-05-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多