5

I am trying to combine multiple expressions in R into a single expression. Ideally, I would be able to do something like this:

g <- expression(exp(a[1]*x)/(1 + exp(a[1]*x)))
h <- expression(exp(a[2]*x)/(1 + exp(a[2]*x)))
c <- expression(g * h)

where a is a given vector of data and x is the only unknown (and it is the same unknown across all expressions). c would return

R> c
expression(exp(a[1]*x)/(1 + exp(a[1]*x)) * exp(a[2]*x)/(1 + exp(a[2]*x)))

Right now, when I do this I just get

R> c
expression(g * h)

I want to have an equation

c
(source: lehrfeld.me)

into which I could plug some vector a to obtain a function of x. What am I doing wrong here?

Community
  • 1
  • 1
Jon
  • 753
  • 8
  • 18
  • 1
    R is not a symbolic algebra program. You should be paying for attention to @thelatemail and at mnel. R is a functional language. – IRTFM Feb 21 '13 at 04:16

5 Answers5

7

Don't use expressions, use functions. The

From what I can decipher, the following will do what you want

# a function for a vector `x` and single value `a`
func <- function(x,a) { (exp(1)^(a*x)/(1 + exp(1)^(a*x))) }
# a function for  a vector `x` and vector length 2 for `a`
foo <- function(x, a){func(x,a[1]) * func(x, a[2])}

# call the function to calculate what you want.

foo(x,a)

And if you want the expression associated with this so you can plot the text of the equation, the following will work

expr <- expression(exp(1)^(a*x)/(1 + exp(1)^(a*x))

g <- do.call(substitute, list(as.list(expr)[[1]], env= list(a=3)))
h<- do.call(substitute, list(as.list(expr)[[1]], env= list(a=2)))
'%c%' <- function(a,b) bquote(.(a) %*% .(b))

fooExpr <- g %c% h
mnel
  • 113,303
  • 27
  • 265
  • 254
6

this is an old question but surprisingly, no easy answer has been given. As said in a comment, "R is not a symbolic algebra program"; however, R has all necessary means for manipulating expressions. I have no idea how to do it with expressions (in the technical sense, see ?expression) but it is trivially easy with calls:

g <- quote(exp(a[1]*x)/(1 + exp(a[1]*x)))
h <- quote(exp(a[2]*x)/(1 + exp(a[2]*x)))
substitute(g*h, list(g=g, h=h))
# exp(a[1] * x)/(1 + exp(a[1] * x)) * (exp(a[2] * x)/(1 + exp(a[2] * x)))

There are probably easier ways to achieve what you want (maybe using functions) but this is the easiest way to merge two "calls" (i.e. expressions in the "colloquial" sense as defined by R wizards).

lebatsnok
  • 6,329
  • 2
  • 21
  • 22
3

Creating the expression from other expressions is more straightforward (IMO) using rlang, than base R. Use the !! (bang-bang) to force evaluation of an object within an expression.

library(rlang)

a <- c(2, 3)
g <- expr(exp(!!a[1] * x) / (1 + exp(!!a[1] * x)))
h <- expr(exp(!!a[2] * x) / (1 + exp(!!a[2] * x)))
c <- expr(!!g * !!h)
c
#> exp(2 * x)/(1 + exp(2 * x)) * (exp(3 * x)/(1 + exp(3 * x)))

Created on 2020-03-21 by the reprex package (v0.3.0)

Daniel D. Sjoberg
  • 8,820
  • 2
  • 12
  • 28
2

You may want a function not an expression I think:

newfunc <- function(x) {
  (exp(1)^(2*x)/(1 + exp(1)^(2*x))) *
  (exp(1)^(3*x)/(1 + exp(1)^(3*x)))
}

a <- 1:10

newfunc(a)
[1] 0.8390245 0.9795856 0.9974043 0.9996585 0.9999543 0.9999938 0.9999992
[8] 0.9999999 1.0000000 1.0000000

If you want to chain together multiple functions explicitly, you could just do:

newfunc1 <- function(x) {
  (exp(1)^(2*x)/(1 + exp(1)^(2*x)))
}

newfunc2 <- function(x) {
  (exp(1)^(3*x)/(1 + exp(1)^(3*x)))
}

newfunc1(a) * newfunc2(a)

Keep in mind, as the help file at ?expression says:

  ‘Expression’ here is not being used in its colloquial sense, that
  of mathematical expressions.  Those are calls (see ‘call’) in R,
  and an R expression vector is a list of calls, symbols etc, for
  example as returned by ‘parse’. 
thelatemail
  • 91,185
  • 12
  • 128
  • 188
  • Thanks for the response. The problem with this is that I don't know exactly the form that each of the individual expressions will take until I examine the data vector `a`. I posted a very simplified version of my problem, which is that I want to specify the combined expression on the fly, and each term in the expression (of which I only showed two above) can take one of three possible forms. So I actually need to build this as I go. – Jon Feb 21 '13 at 03:25
  • @psychometriko - I'm not sure what would be the problem with using the function method. Just add or edit one of the lines in `newfunc` as you go until you are happy. – thelatemail Feb 21 '13 at 04:03
2

You could define a binary function to combine expression objects in a slightly hacky way -- get their character representation, paste them with a *, then re-parse it:

"%c%" <- function(x, y) parse( text=paste(x, "*", y) )

gives the desired output when calling g %c% h, for example.

EDIT: Answer updated to correct previous error; thanks mnel!

Kevin Ushey
  • 20,530
  • 5
  • 56
  • 88
  • Thanks so much for the idea! Once I have a chance to test this, hopefully tomorrow, I will mark this as the answer. – Jon Feb 21 '13 at 03:26
  • 1
    This isn't going to work! it creates an `expression('exp(a[1]*x)/(1 + exp(a[1]*x)) * exp(a[2]*x)/(1 + exp(a[2]*x))')` which isn't the same as `expression(exp(a[1]*x)/(1 + exp(a[1]*x)) * exp(a[2]*x)/(1 + exp(a[2]*x))`. and certainly wont let you pass a vector `a` or `x` to get a function of x that you can evaluate in R – mnel Feb 21 '13 at 03:46
  • Thanks. I was close, but your solution is definitely better. – Kevin Ushey Feb 21 '13 at 18:50