Combining expressions in R
Asked Answered
H

5

6

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?

Hodeida answered 21/2, 2013 at 2:56 Comment(1)
R is not a symbolic algebra program. You should be paying for attention to @thelatemail and at mnel. R is a functional language.Rabiah
A
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
Arturoartus answered 21/2, 2013 at 3:1 Comment(0)
D
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).

Dejecta answered 12/4, 2016 at 13:53 Comment(0)
C
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)

Canyon answered 21/3, 2020 at 12:51 Comment(0)
C
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’. 
Cookbook answered 21/2, 2013 at 3:18 Comment(2)
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.Hodeida
@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.Cookbook
P
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!

Palatalized answered 21/2, 2013 at 3:21 Comment(3)
Thanks so much for the idea! Once I have a chance to test this, hopefully tomorrow, I will mark this as the answer.Hodeida
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 RArturoartus
Thanks. I was close, but your solution is definitely better.Palatalized

© 2022 - 2024 — McMap. All rights reserved.