s-news
[Top] [All Lists]

formula conversion

To: "s-plus" <s-news@wubios.wustl.edu>
Subject: formula conversion
From: "albert horwath" <al_horwath@lycos.com>
Date: Mon, 18 Dec 2000 09:59:22 -0800
Organization: Lycos Communications (http://comm.lycos.com:80)
Reply-to: al_horwath@lycos.com
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

<Prev in Thread] Current Thread [Next in Thread>