在R包中动态创建函数

时间:2013-06-07 13:31:52

标签: r package

我想要包含在一个包中,我有一个动态生成的函数(如果你好奇的话,在底部的扰流器块中解释的原因)。我想以最小的性能损失并且不使用不受支持的功能来实现。到目前为止,我想这样做的方法是将生成函数的代码放入.onLoad(),并将函数存储在options()中,或者作为隐藏对象存储在.GlobalEnv中。显然,将函数存储在.GlobalEnv中是有风险的,因为它可能会被无意中修改或删除。它也可能发生options(),不太可能发生意外。

将生成的函数存储在options()中是最好的方法吗?

  

我有一个多变量函数,用长而丑的衍生物称它为Fn。我想创建另一个函数,它返回该函数的梯度(即每个变量中的一阶导数的矢量,在给定的X处求值)和一个粗体(即在给定的每个变量组合中的二阶导数的矩阵) X)。为了使代码可维护,我只将原始Fn手动编码为未评估的表达式,然后让D()eval()`body<-`()执行其余工作。我最终得到一个动态生成的函数对象,它返回我想要的结果。


Adam Hyland的评论对这个具体问题有最简单的答案。如果您将其作为答案发布,则会被接受。但是,Richie Cotton的答案在一般情况下非常有用,所以也要感谢你。

1 个答案:

答案 0 :(得分:6)

您可以尝试在assignInNamespace内使用.onLoad(未经测试),但就像Adam H在评论中所说的那样,听起来你正在努力做事。

如果我正确理解了这个问题,你有一个导数的表达式,你想要在给定点评估该表达式,并计算该点的梯度,并计算该点的粗糙度。只需创建一个函数,接受一个表达式和一个坐标的数值向量来评估,并让它吐出你想要的所有东西。像这样:

#' Evaluate an expression, its derivative and its hessian
#' 
#' Evaluates an expression, its derivative and its hessian at a given point.
#' @param expr An expression of derivatives
#' @param x A named numeric vector of coords to evaluate \code{expr} at
#' @param name String giving the name of the variable to differentiate by
#' @return A list with the following values
#' \itemize{
#'   \item{value}{The value of \code{expr} evaluated at \code{x}.}
#'   \item{gradient}{The value of the derivative of \code{expr} evaluated at \code{x}.}
#'   \item{hessian}{The value of the hessian of \code{expr} evaluated at \code{x}.}
#' }
#' @examples
#' expr <- expression(sin(cos(x + y^2)))
#' x <- c(x = pi / 2, y = pi / 3)
#' eval_expr_and_calc_grad_and_hessian(expr, x, "x")
eval_expr_and_calc_grad_and_hessian <- function(expr, x, name = names(x)[1])
{
  x <- as.list(x)
  d_by_dname <- D(expr, name)
  d2_by_dname2 <- D(d_by_dname, name)
  list(
    value    = eval(expr, x),
    gradient = eval(d_by_dname, x),
    hessian  = eval(d2_by_dname2, x)
  )
}