【问题标题】:How to find derivative with respect to vectorized variable in R如何在R中找到关于向量化变量的导数
【发布时间】:2020-11-07 12:58:30
【问题描述】:

我在 R 中有以下函数,我可以很容易地找到它关于 x1 或 x2 或 x3 的偏导数:

ppp <- function(x1,x2, x3, m)  { 
n*log(m[1]*exp(x1) + m[2]*exp(x2) + m[3]*exp(x3) + m[4]) 
}
Deriv(ppp, "x3")

如何使函数自动化,以便找到Deriv(ppp, "x[3]") 的导数?

我尝试了类似的方法,但它不起作用:

ppp <- function(x, m)  { 
n*log(m[1]*exp(x[1]) + m[2]*exp(x[2]) + m[3]*exp(x[3]) + m[4]) 
}
Deriv(ppp, "x[1]")

考虑到函数的两个参数m[1]*exp(x[1]) + m[2]*exp(x[2]) + m[3]*exp(x[3]) 的范围从 1 到 3,有没有办法可以用 sum() 重写函数?

【问题讨论】:

    标签: r math derivative


    【解决方案1】:

    您可以围绕Deriv 编写一个包装器,它将下标转换为变量并再次返回:

    library(Deriv)
    
    Deriv_vec <- function(f, var, ...)
    {
      bod <- c(gsub(var, "new_var", as.character(body(f)), fixed = TRUE), "}")
      body(f) <- parse(text = bod)
      formals(f) <- c(alist(new_var=), formals(f))
      result <- Deriv(f, "new_var", ...)
    
      bod <- c(gsub("new_var", var, as.character(body(result)), fixed = TRUE), "}")
      body(result) <- parse(text = bod)
      formals(result) <- formals(result)[-1]
      result
    }
    

    这允许:

    ppp <- function(x, m)  { 
       n*log(m[1] * exp(x[1]) + m[2] * exp(x[2]) + m[3] * exp(x[3]) + m[4]) 
    }
    
    Deriv_vec(ppp, "x[1]")
    #> function (x, m) 
    #> {
    #>     .e1 <- exp(x[1])
    #>     n * .e1 * m[1]/(.e1 * m[1] + exp(x[2]) * m[2] + exp(x[3]) * 
    #>         m[3] + m[4])
    #> }
    
    Deriv_vec(ppp, "x[3]")
    #> function (x, m) 
    #> {
    #>     .e1 <- exp(x[3])
    #>     n * .e1 * m[3]/(.e1 * m[3] + exp(x[1]) * m[1] + exp(x[2]) * 
    #>         m[2] + m[4])
    #> }
    

    如果您需要一个带有多个变量的版本,这会更复杂,但可以这样实现:

    Deriv_vec <- function(f, var, ...)
    {
      for(i in seq_along(var)) {
        bod <- c(gsub(var[i], 
                      paste0("new_var", i),
                      as.character(body(f)), fixed = TRUE), "}")
        body(f) <- parse(text = bod)
      }
      
      new_vars <- paste0("new_var", seq_along(var))
      new_args <- setNames(lapply(seq_along(new_vars), 
                                  function(x) alist(a=)$a), new_vars)
      formals(f) <- c(new_args, formals(f))
      
      result <- Deriv(f, new_vars, ...)
      
      for(i in seq_along(var))
      {
        bod <- c(gsub(new_vars[i], var[i], 
                      as.character(body(result)), fixed = TRUE), "}")
        if(substr(bod[length(bod) - 1], 1, 2) == "c(")
        {
          bod[length(bod) - 1] <- 
            gsub(var[i], paste0("`", var[i], "`"), bod[length(bod) - 1],
                 fixed = TRUE)
        }
        body(result) <- parse(text = bod)
      }
      formals(result) <- formals(result)[-seq_along(var)]
      result
    }
    

    这就允许:

    Deriv_vec(ppp, c("x[1]", "x[2]", "x[3]"))
    #> function (x, m) 
    #> {
    #>     .e1 <- exp(x[1])
    #>     .e2 <- exp(x[2])
    #>     .e3 <- exp(x[3])
    #>     .e7 <- .e1 * m[1] + .e2 * m[2] + .e3 * m[3] + m[4]
    #>     c(`x[1]` = n * .e1 * m[1]/.e7, `x[2]` = n * .e2 * 
    #>         m[2]/.e7, `x[3]` = n * .e3 * m[3]/.e7)
    #> }
    

    请注意您的具体示例。函数ppp 包含一个名为n 的变量。这可能应该作为参数包含在内。

    【讨论】:

    • 这真的很棒,但是我怎样才能传递一个具有多个变量的函数。这就是我的意思 Deriv_vec(ppp, c("x[1]","x[2]"))。我以一般形式考虑它,因为我什至可能想调用两个以上的变量。换句话说,我如何将 gsub() 中的模式参数作为向量而不是长度为 1 传递。
    • @Muhamd 的问题在于,如果您将多个变量传递给Deriv,它会返回一个命名向量。这是根据使用的变量命名的,但x[1]x[2] 在R 中不是合法名称,因此您不能再单独使用gsub 技巧。要使此功能按预期运行需要更多的工作
    • @Muhamd 看到我的编辑。如果有人回答您的问题,请参阅here 以获取有关下一步做什么的建议。谢谢。
    • 有没有办法使用矩阵调用第一个函数输出(仅调用“x[1]”的函数)(下图)。我正在考虑一个多维问题,并且将Deriv 与矩阵一起使用看起来也有点复杂。这就是我的意思:x[1] 可能是x[,1]。调用导数为DD= Deriv_vec(ppp, "x[,1]") 然后我想进行这样的调用DD(x=cbind(c(1.3, 1.6, 2.7),c(1.1, 1.2, 1)), m = c(0.1,0.2,0.8))n 是一个常量,我可以在函数中更改它。我可以想象最大的问题是Deriv。有什么办法吗?
    • @Muhamd 这仍然可以工作,但显然您必须更改 ppp,以便您需要 x[, 1]x[, 2] 等而不是 x[1]x[2] 等。您还需要确保在逗号后传递带有空格的变量,所以"x[, 1]",而不是"x[,1]"
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-31
    • 1970-01-01
    相关资源
    最近更新 更多