[R] Symbolic derivation using D in package stats - how do I properly convert the returned call into a character string?

Duncan Murdoch murdoch at stats.uwo.ca
Tue Nov 21 16:15:17 CET 2006


On 11/21/2006 8:48 AM, Daniel Berg wrote:
> Dear all,
> 
> I am using the function 'D' in the 'stats' package to perform symbolic 
> derivation.
> This works very well and it is much faster than e.g. Mathematica (at 
> least for my purposes).
> First, I would like to thank the development team for this excellent 
> function.
> 
> However, I run into trouble in some cases, particularly when I am to do 
> some operations on long expressions obtained from using D.
> The problem seems to occur when I convert a 'call' or an 'expression' to 
> a 'character', then some parts of the original 'expression' is lost.
> Is there some way of transforming a call or an expression into a 
> character string that I do not know of or alternatively, can I merge two 
> calls or two expressions by a numerical operation, e.g. c = a / b where 
> both a and b are symbolic expressions and I wish for c to be a symbolic 
> expression as well?
> 
> Take e.g. the following example:
> #---------------------------------
> # First, I try with d=2, now it works:
> d<-2; u<-rep("u1",d); th<-rep("th1",d)
> for(i in 1:d) { u[i] <- paste("u",i,sep=""); th[i] <- paste("th",i,sep="") }
> dC1 <- expression((((1 - 2 + u1^(-th1)) + u2^(-th1))^(-1/th1)))
> dC2 <- expression(u1)
> #These expressions were returned from a combination of several 
> expressions of mine...
> for(j in 1:(d-1)) { dC1<-D(expr=dC1,name=u[j]); dC2<-D(expr=dC2,name=u[j]) }
> # I wish to create a new expression equal to dC1 / dC2 and I proceed as 
> follows:
> F <- paste("(",as.expression(dC1),")/(",as.expression(dC2),")",sep="")
> # To see that it works print dC1, dC2 and F and compare.
> 
> # It also works for d=3, but for d=4 something strange happens:
> d<-4; u<-rep("u1",d); th<-rep("th1",d)
> for(i in 1:d) { u[i] <- paste("u",i,sep=""); th[i] <- paste("th",i,sep="") }
> dC1 <- expression((((1 - 2 + u1^(-th1)) + (((1 - 2 + u2^(-th2)) + (((1 - 
> 2 + u3^(-th3)) + u4^(-th3))^(-1/th3))^(-th2))^(-1/th2))^(-th1))^(-1/th1)))
> dC2 <- expression((((1 - 2 + u1^(-th1)) + (((1 - 2 + u2^(-th2)) + 
> u3^(-th2))^(-1/th2))^(-th1))^(-1/th1)))
> for(j in 1:(d-1)) { dC1<-D(expr=dC1,name=u[j]); dC2<-D(expr=dC2,name=u[j]) }
> F <- paste("(",as.expression(dC1),")/(",as.expression(dC2),")",sep="")
> # Now paste(dC1) throws away parts of the expression. Try
> paste(dC1)
> # and see the end of second element.
> # You will get a 3-dim char vector where there is something missing at 
> the end of the second element.
> #-----------------------------------
> 
> I am running R 2.2.1 on windows.
> Any help, suggestions or comments in general will be highly appreciated.

That's an old version, but I think the problem is still present in the 
current one.  A simple example is

paste(as.expression(as.list(1:1000)))

which on my system truncates the output just after the 121st element of 
the list.

The problem is that deparse() has a maximum line width of around 500 
characters, and you need more to fit your entire expression on one line, 
the way paste is trying to do.

I suppose we could increase the buffer size in deparse (or make it 
dynamic), but I'm not sure that it's worthwhile.  Why would you want to 
use paste on a long expression like that?  Why not leave it as an 
expression?  deparse() works fine to print it on multiple lines; I'm 
just not sure I see the value in allowing arbitrarily long lines here.

(At a minimum, I think paste() should report a "line too long" error 
rather than silently truncating; I'm not saying the current behaviour is 
fine.)

Duncan Murdoch



More information about the R-help mailing list