【问题标题】:Symbolic derivatives on formulas公式上的符号导数
【发布时间】:2013-10-17 20:16:55
【问题描述】:

在 R 中,我想要一种方法来获取公式右侧的符号导数,其中可能包括交互项、平方项等。

例如,我希望能够对以下两个 [edit:three] 公式中的每一个求得右手边关于 x 的导数:

y~x+I(x^2)

y~x:z

编辑:y~x*z

我想要一个函数,当输入上述三个公式时,分别返回1+2x、z和1+z。

我尝试了以下方法:

f1<-y~x+I(x^2)
deriv(f1,"x")
## Error in deriv.formula(f1, "x") : Function 'I' is not in the derivatives table

f2<-y~x:z
deriv(f2,"x")
## Error in deriv.formula(f2, "x") : Function '`:`' is not in the derivatives table

有什么方法可以强制 R 将 I(x^2)(或类似地,I(x*z) 等)识别为 x^2(分别为 x*z),x:z 识别为 x *z(在数学意义上)和 x*z(在公式意义上)作为 x+z+x*z(在数学意义上)用于计算导数?

其次,有没有办法从 deriv() 获取输出并将其重塑为看起来像公式的右侧?特别是,我知道 D() 将缓解这个问题并以我想要的形式生成输出(尽管 D() 不能将公式作为输入处理),但是如果我想对多个变量进行导数怎么办?我可以通过对每个我想对其进行导数的变量反复应用 D() 来解决这个问题,但是最好简单地输入所有这些变量的字符串并接收适合放置的输出在公式的右侧。

谢谢!

【问题讨论】:

  • 请详细解释为什么y~x:z 应该返回1+x。 (在 R 中,x*z1+x+z+x:z不是相反。)
  • @DWin :抱歉,应该说是x*z,这实际上引发了另一个问题——R 将公式中的x*z 解释为1+x+z+x:z,但如果你通过deriv(y~x*z,"x"),这会产生z 作为导数,它应该是 1+z。关于x:z,它实际上应该返回z,而不是1+z(在原始问题中进行编辑)。
  • deriv 函数使用“*”的数学定义,而“:”没有数学定义。请编辑您的问题以清除错误并重新构建以提出合法请求。仅仅说一个函数的行为不像你想象的那样是没有帮助的。如果需要,您需要对新功能提出合理且具体的要求。
  • 对。我的问题是我是否可以强制它在输入公式中将x:z 识别为数学上的x*z(或者,进一步,将x:z:a 识别为x*z*a)和x*z,在输入公式中识别为@987654341 @数学上。
  • 我很抱歉。我并不是说deriv 有任何问题,只是询问是否有办法强制它识别我以我想要的方式提供的输入(我认为这是相当直观的)。我已经编辑了这个问题以反映这一点,尽管我认为它一直都有合理和具体的要求。

标签: r formula derivative


【解决方案1】:

如果你有一个公式表达式,你可以使用substitute():

substitute( x~x:z+x:y , list(`:`=as.name("*") ) )
x ~ x * z + x * y

这将允许您将表达式对象传递给substitute,并首先对其进行评估(否则不会发生这种情况,因为substitute 不会评估其第一个参数):

form1 <- expression(x ~ x : z + x : y)
rm(form2)
form2 <- do.call('substitute' , list(form , list(`:`=as.name("*") ) ))
form2
# expression(x ~ x * z + x * y)

这显示了如何“重塑”RHS,以便通过从列表结构中提取 RHS 来像 ~ x*z 一样处理 y ~ x:z,其中波浪号运算符被视为一个函数,而 LHS 是 @ 中的第二个元素987654329@:

 f2<-y~x:z
 substar <- function(form) { 
            do.call('substitute' , list(form , list(`:`=as.name("*") ) )) }
 f3 <- substar(f2)
 deriv(f3[[3]],"x")
 #----------------------
expression({
    .value <- x * z
    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
    .grad[, "x"] <- z
    attr(.value, "gradient") <- .grad
    .value
})

如果您想使用表达式,可能有助于理解它们是像列表一样组织的,并且操作符实际上是类似 Lisp 的函数:

> Z <- y~x+I(x^2)
> Z
y ~ x + I(x^2)
> Z[[1]]
`~`
> Z[[2]]
y
> Z[[3]]
x + I(x^2)
> Z[[3]][[1]]
`+`
> Z[[3]][[2]]
x
> Z[[3]][[3]]
I(x^2)
> Z[[3]][[3]][[1]]
I
> Z[[3]][[3]][[2]]
x^2
> Z[[3]][[3]][[2]][[1]]
`^`

如果你想查看一个遍历表达式树的函数,几年前在 Rhelp 中构建的独一无二的 Gabor Grothendieck:http://markmail.org/message/25lapzv54jc4wfwd?q=list:org%2Er-project%2Er-help+eval+substitute+expression

【讨论】:

  • 这很有帮助,谢谢。您是否知道一个网站或其他资源会列出此类表达式的层次结构(例如,为什么Z[[1]] 波浪号、Z[[2]] y 等)?此外,是否有某种方法可以提取某种类型的所有术语(例如,由I() 括起来的所有术语)?
  • 你可以看看github.com/lme4/lme4/blob/master/R/utilities.R 中的findbars 函数——不简单,但它做了类似的任务......
【解决方案2】:

deriv?deriv)的帮助文件说deriv函数中的expr参数是一个“ 表达式或调用或(D 除外)没有 lhs 的公式”。因此,您不能在表达式中使用等式的左侧。

在问题的第二部分,如果我正确理解了您的问题,您可以这样做:假设您的 rhs 是 x^2+y^2 并且您需要使用 x 和 y 对该表达式进行偏导:

myexp <- expression((x^2) + (y^2))
D.sc.x <- D(myexp, "x")
> D.sc.x
2 * x
D.sc.y <- D(myexp, "y")
> D.sc.y
2 * y

一行:

lapply(as.list(c("x","y")),function(a)D(myexp,a))
[[1]]
2 * x

[[2]]
2 * y

【讨论】:

  • 这并不能真正回答我的问题。我的问题是我希望能够对公式的右手边求导[顺便说一下,deriv() 能够处理公式——试试 deriv(y~x^2,"x")——它只是剪掉 LHS 并取 RHS 的导数]。但是,如果我传递一个包含 I(x^2) 或 x:z 之类的公式,它就不知道如何处理这些事情。其次,我不想采取两个部分。例如,我想拍第二个混合部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-05
  • 1970-01-01
  • 2020-09-25
  • 1970-01-01
  • 1970-01-01
  • 2014-04-07
  • 1970-01-01
相关资源
最近更新 更多