在R包中动态创建函数 [英] Dynamically creating a function within an R package

查看:79
本文介绍了在R包中动态创建函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个动态生成的函数(如果您好奇的话,请在底部的扰流块中说明原因),我想将其包含在程序包中.我想以最小的性能损失并且不使用不受支持的功能来做到这一点.到目前为止,我想到的方法是将生成函数的代码放入.onLoad()中,然后将函数存储在options()中,或者将其存储为.GlobalEnv中的隐藏对象.显然,将函数存储在.GlobalEnv中是有风险的,因为可以无意间对其进行修改或删除. options()也可能发生这种情况,偶然发生的可能性较小.

I have a dynamically generated function (for reasons explained in the spoiler block at the bottom if you're curious) that I want to include in a package. I want to do so with minimal performance penalty and without using unsupported functionality. The way I thought of doing this so far is putting the code that generates the function into .onLoad() and either storing the function in options() or as a hidden object in .GlobalEnv. Obviously storing the function in .GlobalEnv is risky because it can be unintentionally modified or deleted. It can happen with options() too, less likely by accident.

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

Is storing generated functions in options() the best way to go?

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

I have a multivariate function, call it Fn with long, ugly derivatives. I would like to create a another function that returns a gradient of that function (i.e. a vector of first derivatives in each variable, evaluated at a given X) and a hessian (i.e. matrix of second derivatives in each combination of variables evaluated at a given X). To make the code maintainable, I only hand-code the original Fn as an unevaluated expression then let the D(), eval(), and `body<-`() do the rest of the work. I end up with a dynamically generated function object that returns the results I want.


亚当·海兰德(Adam Hyland)的评论对这个特定问题有最简单的答案.如果您将其发布为答案,它将被接受.但是,在一般情况下,Richie Cotton的答案非常有用,因此也谢谢您.


Adam Hyland's comment has the simplest answer to this specific question. If you post it as an answer, it will be accepted. However, Richie Cotton's answer is very useful in the general case, so thank you as well.

推荐答案

您可以尝试在.onLoad内使用assignInNamespace(未经测试),但是就像Adam H在他的评论中说的那样,听起来您在做事很辛苦方式.

You could try using assignInNamespace inside .onLoad (not tested) but like Adam H said in his comment, it sounds like you are doing things the hard way.

如果我正确理解了该问题,则您有一个导数表达式,并且想要在给定点上对该表达式求值,并在该点处计算梯度,并在该点处计算粗麻布.只需创建一个接受表达式和座标数值矢量的函数,然后将其吐出您想要的所有内容即可.像这样:

If I've understood the question correctly, you have an expression of derivatives, and you want to evaluate that expression at a given point, and calculate the gradient at that point, and calculate the hessian at that point. Just create a function that accepts an expression and a numeric vector of coordinates to evaluate at, and have it spit out all the things you want. Something like this:

#' 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)
  )
}

这篇关于在R包中动态创建函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆