Dear S-colleagues:
Many thanks to s+ wizards Bert Gunter
and Samuel Buttrey for help with my request
on "formula conversion". Combining their ideas I managed to solve
my problem.
Here is the original posting
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Suppose that I have an expession:
y<-2+x+ a*sin(x)+b*exp(x)+c*x^1.3
I need to create a formula
y~x+sin(x)+exp(x)+x^1.3
And vice versa:
I have a formula
y~x+sin(x)+exp(x)+x^1.3
and coefficients: c0,c1,c2,c3,c4
I need to compute ( I mean to create an expression and evaluate it)
y<-c1+c2*x+ c3*sin(x)+c4*exp(x)+c5*x^1.3
Is that possible to automatically do this kind of conversions in s+?
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Here are the answers (slightly edited)
Here's a way to do the second, as long as it's always an additive model,
so that the separators on the right side are always +'s.
> f <- y~x+sin(x)+exp(x)+x^1.3 # your formula
> x <- 2 # set a value for x
> coefs <- c(1,2,3,4,5) # some coefficients; the first is the constant term
> df <- as.character(f) # puts " ~ " into df[1], "y" into df[2], everything
else into df[3]
> rhs.pieces <- unlist (unpaste (df[3], sep="+")) # separate pieces
> my.expr <- paste (df[2], "<-", coefs[1], "+", paste (coefs[-1], "*",
rhs.pieces, collapse="+")) # put it together...
> eval (parse (text = my.expr))
[1] 49.59556
> 1 + 2 * x + 3 * sin(2) + 4 * exp(2) + 5 * 2^1.3 # check
[1] 49.59556
Okay. The first is a little trickier, but again unpaste (twice) can do the
trick, again assuming there are only *'s and +'s.
f <- expression (y<-2+x+ a*sin(x)+b*exp(x)+c*x^1.3) # starting point
f <- as.character(f) # convert to character
less.than <- (1:nchar(f))[substring (f, 1:nchar(f), 1:nchar(f)) == "<"]
lhs <- substring (f, 1, less.than - 2) # extract lhs; skip
space and "<"
rhs <- substring (f, less.than + 2, nchar(f)) # extract rhs: skip hyphen and
space
rhs.pieces <- unlist (unpaste (rhs, sep="+"))[-1] # break up, discard
constant
#
# Omit the first piece, which has no "*" in it. To each of the remaining
pieces, apply the unpaste function. The
# result is a matrix from which we want the second row.
#
rhs.pieces[-1] <- unlist (sapply (rhs.pieces[-1], unpaste, sep="*")[2,])
new.expr <- parse (text = paste (lhs, "~", paste (rhs.pieces,
collapse="+")))
Sam Buttrey
~~~~~~~~~~~~~~~~~~~~~~~~
These tasks are fairly easy using unpaste()
> z_"5+4x+9x^2"
> terms<-unpaste(z, sep="+")
> terms
[[1]]:
[1] "5"
[[2]]:
[1] "4x"
[[3]]:
[1] "9x^2"
Now you can use lapply to remove the first character from each component
with substring():
> terms_lapply(terms, function(x)substring(x,2))
> terms
[[1]]:
[1] ""
[[2]]:
[1] "x"
[[3]]:
[1] "x^2"
You can now unlist() this into a vector and use paste on the NONconstant
terms to rebuild the formula -- you paste the constant term on afterwards.
> cf_c(3,5)
> paste(cf,unlist(terms)[-1],sep="*",collapse='+')
[1] "3*x+5*x^2"
Bert
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Thanks again
Albert Horwath
Get FREE Email/Voicemail with 15MB at Lycos Communications at
http://comm.lycos.com
|