【问题标题】:Issue on renaming functions关于重命名函数的问题
【发布时间】:2020-10-13 19:03:20
【问题描述】:

我正在编写一些代码来计算函数的导数。我设法为 1 个变量生成一阶和二阶导数,并将其作为函数存储在环境中,以便稍后绘制它们。现在我正在尝试计算具有 2 个或更多变量的方程的偏导数,但我找不到可以在环境中生成与函数的偏导数一样多的函数的代码。

为了澄清,我使用了 1 个变量:

    f <- function(x) cos(20*x)*exp(-1*x)
    F.<- function (x) eval(D(as.expression(body(f)), "x"))
    F..<- function (x) eval(D(as.expression(D(as.expression(body(f)), "x")),"x"))

而且效果很好,我在环境中获得了 3 个功能:

但是对于超过 1 个变量,我必须遍历这些函数并生成与方程的偏导数一样多的函数。

我的问题是:如何生成一个循环来计算函数的偏导数并将它们存储为函数,每个函数都有一个自定义名称?

我在 for 循环中尝试了导数函数,但无法为导数的每次计算定义不同的名称:

    for (i in 1:nro_variables) {
      var_D = vector_variables[i]  
      F.<- function (x) eval(D(as.expression(body(f)), var_D))
    }

【问题讨论】:

  • 您能否举一个函数示例,该函数具有多个变量,以及您期望从该输入获得的输出?这样就可以测试和验证可能的解决方案。
  • @MrFlick,是的。假设我将函数“f”定义为:f= -log(1-x-y)-log(x)-log(y)。它的偏导数是:F.= 1/(1-x-y)-1/x 对于“x”,F.= 1/(1-x-y)-1/y 对于“y”。我正在尝试将两个方程以不同的名称存储在环境中(例如:“F.x”表示相对于“x”的偏导数,“F.y”表示相对于“y”的偏导数)

标签: r function derivative


【解决方案1】:

类似于避免使用分配许多单独的相似对象来淹没您的全局环境,考虑使用可以索引元素的单个列表以更好地进行序列组织。查看@GregorThomas 的最佳实践answer 倡导:

首先不要创建d1 d2 d3, ..., dn。使用 n 元素创建列表 d

具体来说,如果vector_variables 是一个字符向量,则使用simplify=FALSEsapply 将返回一个命名的函数列表。是的,列表中的函数仍然可以被调用。

partial_deriv_funcs <- sapply(vector_variables, function(var_D) {
    f <- function(x) cos(20*x)*exp(-1*x)
    return(function(x) eval(D(as.expression(body(f)), var_D)))
}, simplify = FALSE)

单独或迭代调用函数元素:

# CALL SINGLE FUNCTION WITH SINGLE PARAM
result <- partial_deriv_funcs[['var1']](param)

# CALL SAME FUNCTION WITH VECTOR OF PARAMS
results <- lapply(param_vector, partial_deriv_funcs[['var1']])

# CALL ALL FUNCTIONS USING SAME PARAM
results <- lapply(partial_deriv_funcs, function(f) f(param))

# CALL ALL FUNCTIONS EACH WITH DIFFERENT PARAM
results <- mapply(function(f,p) f(p), partial_deriv_funcs, param_per_func_vector, SIMPLIFY= FALSE)
results <- Map(function(f,p) f(p), partial_deriv_funcs, param_per_func_vector) # EQUIVALENT

【讨论】:

  • 感谢@Parfait,效果很好!我添加了一个 For...循环来添加列表中每个元素的“环境”值,并通过为偏导数选择的变量更改了默认值 (vector_variables)。现在我可以打印导数方程并用它来评估值并绘制它们。
  • 太棒了!很高兴听到并乐于提供帮助。
【解决方案2】:

evalparse 可以用来定义函数,assign 可以给它正确的名字。

f <- function(x) 2 * x
g <- function(x, y) x * y
h <- function(x, y, z) x * y + z

fns <- c("f", "g", "h")

for (fn in fns) {
  for (variable in formalArgs(fn)) {
    function_name <- glue::glue("{toupper(fn)}.{variable}")
    fn_definition <- eval(parse(text = glue::glue("function({paste0(formalArgs(fn), collapse = ',')}) eval(D(as.expression(body({fn})), '{variable}'))")))

    assign(
      function_name,
      fn_definition
    )
  }
}

ls.str(mode = "function")
#> f : function (x)  
#> F.x : function (x)  
#> fn_definition : function (x, y, z)  
#> g : function (x, y)  
#> G.x : function (x, y)  
#> G.y : function (x, y)  
#> h : function (x, y, z)  
#> H.x : function (x, y, z)  
#> H.y : function (x, y, z)  
#> H.z : function (x, y, z)  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-27
    • 2016-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多