I would like to create a function in which a mathematical formula is set as argument (with only two possible variables) and use this formula within two nested loop. The idea is to be able to change the formula as I would like to create y values based on the formula. This is what I have done but I cannot apply the formula:
foo <- function(formula = y~a-b){
formula = as.formula(y ~a -b)
formula = formula[[3:length(formula)]]
result = NULL
for (a in 1:30) {
for(b in 1:30){
result = c(result, noquote(formula))
}
}
return(result)
}
CodePudding user response:
Create a template fun and then insert the formula into its body.
foo <- function(formula = y ~ a - b) {
fun <- function(a, b) {}
body(fun) <- formula[[length(formula)]]
result <- NULL
for (a in 1:30) {
for(b in 1:30) {
result = c(result, fun(a, b))
}
}
return(result)
}
# test
result <- foo()
CodePudding user response:
I like the solution that G. Grothendieck
provided. Here is another way to do this, where you have foo()
take a character representation of the formula, and use as.function()
foo <- function(f) as.function(alist(a=,b=,eval(parse(text=f))))
a=1:5
b=1:5
f = "(a-b)*a/b"
result = apply(expand.grid(a,b),1,\(x) foo(f)(x[1],x[2]))
Output:
[1] 0.0000000 -0.5000000 -0.6666667 -0.7500000 -0.8000000 2.0000000 0.0000000
[8] -0.6666667 -1.0000000 -1.2000000 6.0000000 1.5000000 0.0000000 -0.7500000
[15] -1.2000000 12.0000000 4.0000000 1.3333333 0.0000000 -0.8000000 20.0000000
[22] 7.5000000 3.3333333 1.2500000 0.0000000
CodePudding user response:
Using alist
and as.function
, and outer
instead of double for
loop.
foo1 <- function(fo=y ~ a - b, a=1:30, b=1:30) {
f <- as.function(c(alist(b=, a=), fo[[3]]))
outer(b, a, f) |> as.vector()
}
## test
result <- foo() ## G. Grothendieck's
result1 <- foo1()
stopifnot(all.equal(result, result1))