I'd like to define a function f from parameters and an expression that are character strings read from a .csv file.
This function f has the following expression :
f = function( parameters ) { expression }
where parameters are a list of n parameters and the expression is a function of these parameters.
For example: the parameters are x1,x2,x3, and expression is (x1+x2)*x3.
The function f is then f = function(x1,x2,x3){ (x1+x2)*x3 }.
How I proceed in R to define such functions ?
EDIT add more context:
Given 2 charcaters strings , for body and arguments
body="(x1+x2)*x3"
args = "x1,x2,x3"
How we can get ?:
function (x1, x2, x3)
(x1 + x2) * x3
Note that this question is similar but don't answer exactly this one, since the solution proposed don't create the function formals (arguments) from a character string.
eval() and parse(), used together, may help you do what you want:
body <- "(x1 + x2) * x3"
args <- "x1, x2, x3"
eval(parse(text = paste('f <- function(', args, ') { return(' , body , ')}', sep='')))
# Text it:
f(3,2,5)
## 10
The explanation: parse() will return the parsed, but unevaluated, expression. I use the text argument in the function to pass a string to the parser. eval() will evaluate the parsed expression (in this case, it will execute the code block you've just parsed).
Hope this helps
Related
I have such a problem, I want to define the grad function as an input of the function. Please see the example below.
f<-function(grad="2*m-4"){
y=grad
return(y)
}
f(3)=2
I'm usually not a fan of using eval(parse(text=..)), but it does do this with a character string:
f <- function(m, grad="2*m-4"){
eval(parse(text = grad))
}
f(3)
# [1] 2
The two take-aways:
if your grad formula requires variables, you should make them arguments of your function; and
parse(text=..) parse the string as if the user typed it in to R's interpreter, and it returns an expression:
parse(text="2*m - 4")
# expression(2*m - 4)
This expression can then be evaluated with eval.
I want to write a function. However, the assumption is that I don't know the input arguments of the function. I just have a character vector to define input arguments of the function. Consider the following code:
f <- expression(exp(-d^2/s^2) )
fx <- function(d, s){ eval( f[[1]] ) }
In the above code, I know the parameters of expression and easily define a calculative function for it. But I get the expression from the user and I don't know what are the parameters. So, I want something like this:
f <- expression(exp(-d^2/s^2) )
v = all.vars(f)
#"d" "s"
fx <- function(?){ eval( f[[1]] ) }
I want to convert v to d and s on input function instead of ?. Is there any way?
There are a few ways to construct functions programmatically, one being:
body <- quote(exp(-d^2/s^2))
arg_names <- all.vars(body)
args <- setNames(rep(NA,length(arg_names)),all.vars(body))
fx <- as.function(c(args,body))
> fx(1,1)
[1] 0.3678794
I have the following problem: I'm writing a function which first constructs a long character string which stands for a mathematical function, e.g. "1/(1+exp(-x1+4x3))". I now want to maximize this function, but unfortunately I cannot do so because the mathematical function is only saved as a character string and not as an R-function. How can I solve this problem? Thanks in advance!
If we know what the arguments are ahead of time then (1) would be preferred as it is simpler (4 lines of code) but if we don't then (2) covers generating them as well (8 lines of code).
1) dynamic body This will convert the string s into a function f2 of 2 arguments which we can call from f1 having one argument as required by optim:
s <- "1/(1+exp(-x1+4*x3))" # test input
f1 <- function(x) do.call("f2", as.list(x)) # f1 calls f2
f2 <- function(x1, x3) {}
body(f2) <- parse(text = s)
optim(c(0, 0), f1, control = list(fnscale = -1))
2) dynamic body + dynamic args In the above we dynamically created the body from the string assuming we knew the arguments but if you want to dynamically create both the body and arguments then try this. Here f2 no longer necessarily has 2 arguments but has nv arguments and what they are is derived from the input s.
s <- "1/(1+exp(-x1+4*x3))" # test input - same as above
f1 <- function(x) do.call("f2", as.list(x)) # function on one argument - same as above
# f2 has nv arguments
f2 <- function() {}
p <- parse(text = s)
v <- all.vars(p) # character string of variable names used for arguments
nv <- length(v)
formals(f2) <- setNames(rep(alist(x=), nv), v)
body(f2) <- p
optim(numeric(nv), f1, control = list(fnscale = -1)) # first arg different from (1)
I'm writing a function which first constructs a long character string which stands for a mathematical function
Don't do that. I'm sure there is a better approach.
because the mathematical function is only saved as a character string and not as an R-function
You'd need to parse the string (after making it valid R syntax):
expr <- parse(text = gsub("((?<=\\d)[[:alpha:]])", "\\*\\1","1/(1+exp(-x1+4x3))", perl = TRUE))
Then you can use this expression to "find the maximum" with whatever method you'd like to use.
However, as fortune 106 says:
If the answer is parse() you should usually rethink the question.
I'm trying to create a function that can evaluate multiple independent expressions. My goal is to input many expressions at once like myfunction(x = 2, y = c(5,10,11) , z = 10, ...), and use each expression's name and value to feed other functions inside of it. The transform() function works kind of like that: transform(someData, x = x*2, y = y + 1).
I know I can get the name and the value of an expression using:
> names(expression(x=2))
[1] "x"
> eval(expression(x=2))
[1] 2
However, I don't know how to pass those expressions through a function. Here is some of my work so far.
With unquoted expression (x=2) I could not pass it using the dots (...).
> myfunction <- function(...) { names(expression(...)) }
> myfunction(x=2)
expression(...)
Now, using quotes. It gets the value but not the name. Parse structure is different from the tradicional expression. See class(expression(x=2)) and class(parse(text="x=2")), then str(expression(x=2)) and str(parse(text="x=2")).
> myfunction <- function(...) {
assign("temp",...)
results <- parse(text=temp)
cat(names(results))
cat(eval(results))
}
> myfunction("x=2")
> 2
So, any ideas?
It's unclear exactly what you want the return of your function to be. You can get the names and expressions passed to a function using
myfunction <- function(...) {
x<-substitute(...())
#names(x)
x
}
myfunction(x = 2, y = c(5,10,11) , z = 10)
Here you get a named list and each of the items is an unevaluated expression or language object that you can evaluate later if you like.
I would like to use microbenchmark::microbenchmark(), but with arguments in the ... that I programatically construct, with strings.
Example :
# classic way
microbenchmark(head(1:1e6), head(1:1e8), times = 10) # (interesting...)
# define my arguments
functionStrings <- lapply(c(6,8), function(ni) paste0("head(1:1e", ni, ")"))
# will not work
do.call(microbenchmark, lapply(functionStrings, function(vi) parse(text=vi)))
The problem here is that microbenchmark works with unevaluated expressions, of class "language", that it then deparse(). Doing deparse() on a normal expression unfortunately deparse the expression object...
bla <- quote(head(1:1e6))
blou <- parse(text = "head(1:1e6)")
eval(bla) ; eval(blou) # Same thing, but....
deparse(bla)
deparse(parse(text = "head(1:1e6)"))
How to get from a string or an expression (argument or output of parse() above) to a language object (output of quote() above) ?
The anonymous function in the last line of the first block of code should be:
function(vi) parse(text=vi)[[1]]
That is:
the argument to parse is named text and not test and
a call object is needed rather than an expression so use [[1]] .