'How do I define a list/vector of functions in R?
I have a function which takes another function as an input variable, eg.
WrapperFunction <- function(x, BaseFunction){
y <- cor(x)
BaseFunction(y)
}
Now I want to input various BaseFunctions into this WrapperFunction, to produce a vector of outputs, but how do I define a list of functions so that instead of plugging in each function by hand, I can automate the process with a for loop:
for (i in 1:n){
output[i] <- WrapperFunction(x, FunctionList[i])
}
I've tried defining
FunctionList <- list()
FunctionList[1] = Function1 , etc....
, which didn't work.
Nor did defining
FunctionList <- c("Function1", "Function2", ...)
Solution 1:[1]
If you want to have a list of functions, you can do something like:
myFuns <- list(mean, sd)
And then you can lapply over this list, or use the for loop as you wanted. If you use the for loop make sure that you use the [[ syntax, because this makes sure that you are retrieving the function and not a length one list:
for (i in 1:n){
output[i] <- WrapperFunction(x, myFuns[[i]])
}
or
lapply(myFuns, WrapperFunction, x = x)
Solution 2:[2]
I'm not sure what you're using for your x value, I presume it's a matrix. You can put some functions into a list then use lapply.
For example
m <- matrix(1:6, 2)
lst <- list(cov, diff)
lapply(lst, WrapperFunction, x = m)
#[[1]]
# [,1] [,2] [,3]
#[1,] 1.848893e-32 -6.162976e-33 -6.162976e-33
#[2,] -6.162976e-33 1.848893e-32 -6.162976e-33
#[3,] -6.162976e-33 -6.162976e-33 1.848893e-32
#
#[[2]]
# [,1] [,2] [,3]
#[1,] -2.220446e-16 2.220446e-16 0.000000e+00
#[2,] 0.000000e+00 -2.220446e-16 2.220446e-16
Also, as suggested by @nrussell, you can vectorize the BaseFunction argument, which is essentially the same as doing the above.
vWF <- Vectorize(WrapperFunction, vectorize.args = "BaseFunction")
vWF(m, lst)
This produces the same result as shown above.
Solution 3:[3]
A slightly different way, Hope this answers your question ...
## Function 1
fun1 <-function(a)
{
a = a+a
return(a)
}
## Function 2
fun2 <- function(a)
{
a = a*a
return(a)
}
## Function 3
fun3 <- function(a)
{
a = a^a
return(a)
}
## Vector of function names
funlist <- c("fun1","fun2","fun3")
## Main Wrapper fnction
mainfun <- function(x,funlist)
{
y = cor(x[,1],x[,2])
res=NULL
for(i in 1:length(funlist))
{
k <- eval(parse(text=paste(funlist[i],"(a=",y,")",sep="")),env=.GlobalEnv)
res <- c(res,k)
}
return(c(y,res))
}
#############
x=cbind(c(1:100),c(101:200))
mainfun(x,funlist)
[1] 1 2 1 1
Solution 4:[4]
I know it's an old post but let me add my two cents on while you're aggregating functions into a list, especially in the way to manipulate them for making bstract calls on your aggregated functions
let me retake the example below where we aggregate avg & st function
list_test <- list( avg=mean, std_dev=sd)
list_test
$avg
function (x, ...)
UseMethod("mean")
<bytecode: 0x000001d32be1ef00>
<environment: namespace:base>
$std_dev
function (x, na.rm = FALSE)
sqrt(var(if (is.vector(x) || is.factor(x)) x else as.double(x),
na.rm = na.rm))
<bytecode: 0x000001d33bed49a0>
<environment: namespace:stats>
we can see when we call the list, it will send back the function definition. If you use the RStudio completion while manipulating list_temp, you'll get something like this
> v_test = rnorm(100)
> list_test$avg(v_test)
[1] 0.1973988
if you proceed without the (), you'll get the definition
list_test$avg
function (x, ...)
UseMethod("mean")
<bytecode: 0x000001d32be1ef00>
<environment: namespace:base>
if you combine with the other way to manipulate r list objects, you'll get:
> list_test[[1]](v_test)
[1] 0.1973988
> list_test[["avg"]](v_test)
[1] 0.1973988
it's the kind of R subtleties I love and you can imagine what it can offer if you use a package like purrr :)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | thothal |
| Solution 2 | |
| Solution 3 | Ashwin |
| Solution 4 | Bruno Sarrant |
