Is there R code to test if variable is a function - r

I am trying to write a function myfun in which one of the variables fun, say, is itself a function. A simple, but ludicrous, example is:
myfun <- function(fun){
return(fun(1))
}
In line with good practice, I want to insert into myfun a test of fun to ensure that fun is indeed a function.
But I can't find code for any such test. What should I do?

You can use is.function to check if some object is a function, for example:
is.function(mean) or is.function(`[[`) would return TRUE, also on a side note there is another function is.primitive which tests for builtins and specials, but in your case you probably would want is.function
In your case :
myfun <- function(fun){
if(is.function(fun)){
return(fun(1))
} else {
warning("You are not passing fun as function")
}
}
Testing using:
fun <- function(x)x+2
would yield 3, but fun <- 1 it would give you warning for calls on myfun(fun)

Related

Error in genereting_fuction(100) : could not find function "genereting_fuction

I created this function to generate the data with the characteristics I need:
genereting_fuction<-function(n){
X1=rnorm(n)+mean_shifts[1]
X4=rnorm(n)+mean_shifts[4]
X2=X1*p12+std_e2*rnorm(n)+mean_shifts[2]
X3=X1*p13+X4*p43+std_e3*rnorm(n)+mean_shifts[3]
X5=X2*p25+X3*p35+std_e5*rnorm(n)+mean_shifts[5]
sample=cbind(X1,X2,X3,X4,X5)
return(sample)
}
if I call it for a single item it works but when I call it in the applay function as follows:
dati<-lapply(1:100, genereting_fuction(100))
I get this error:
Error in genereting_fuction(100) :
could not find function "genereting_fuction"
Note that I prefer the replicate solution by #Jakub.Novotny for your purpose, but to understand what went wrong using lapply, this is why and how to solve it.
Using apply and a function, it assumes x the value of your apply to be provided always in the function.
To make it work you can do two things.
lapply(1:100, function(x) genereting_fuction(100))
include x in your function like genereting_fuction <- function(x, n) { # code here } and then you can use lapply(1:100, genereting_fuction, n = 100)

Can I call a function in R if it's argument is not defined?

Out of pure curiosity, I want to make a function in R that creates a new variable. I don't want the function to ask the user for input while it is running. Suppose x is not currently a variable. Below is an example of what I want the code to do:
def=function(x){
x=NULL
}
def(x)
x
NULL.
substitute allows you to delay evaluation of the variable, as.character turns it into the typed name, if we then assign it in the parent.frame() to the value, we get what you're after.
def <- function(x) {
y <- substitute(x)
assign(as.character(y),NULL,envir = parent.frame())
}
> def(test)
> test
NULL

When passing a function as an argument to another function, how do I loop over that function?

I currently set up a function which takes another function as an argument. I am trying to create this function to loop over the function it took as an argument.
However, with the way I set it up, it seems like it only really runs the function once, as it should be dependent on a random seed but it keeps coming back with the exact same value.
The only way I found to solve this was to not have the function as an argument but to hard code it in to the function, but this is not really what I want to do.
Here is my code:
runModel <- function(model,runs){
b = c()
for (i in 1:runs){
a <- model$lambda.min
b <- append(b,a)
}
return (c(mean(b),sd(b)))
}
cvModel = cv.glmnet(predictors,outcome,family=c("binomial"),alpha=.9,nfolds=20)
runModel(cvModel,20)
I don't know what are your objects 'predictors' or 'outcome' but it looks like your passing the result of your function cv.glmnet rather than the expression of your function to your runModel function.
One way to run the function at each loop could be to rewrite your function to pass function name and arguments:
runModel <-function(fun,runs,predictors,outcome,family=c("binomial"),alpha=.9,nfolds=20){
b = c()
model <- fun(predictors,outcome,family,alpha,nfolds)
for (i in 1:runs){
a <- model$lambda.min
b <- append(b,a)
}
return (c(mean(b),sd(b)))
}
runModel(cv.glmnet,20, predictors,outcome,family=c("binomial"),alpha=.9,nfolds=20)

Use optimize() for a function which returns several values

Easier to ask by example. If I have a function
fn <- function(x) {
...
return(c(a,b,c))
}
and I wish to maximize (or minimize) with respect to a, but also get the values of b and c at the optimal value.
Of course I can use fn2 <- function(x) fn(x)[1] to determine the optimal value, then call the function again, but I wonder if there is a smarter way of doing this.
optim needs the return value to be a scalar. The documentation says so
fn: A function to be minimized (or maximized), with first
argument the vector of parameters over which minimization is
to take place. It should return a scalar result.
You could write the values of interest to a global variable inside your function though. This isn't necessarily best practice but it could work.
f <- function(x){
.vals <<- c(x, x+1)
x^2
}
optim(1, f)
then after we can look at what is stored in .vals
> .vals
[1] 9.765625e-05 1.000098e+00

Initializing function arguments in the global environment R

I'm looking for a simple function to speed up my ability to write and debug R functions. Consider the following blocks of code:
# Part A:
myfun = function(a, b = 5, out = "hello"){
if(a>b) print(out)
return(a-b)
}
# Part B:
b = 5
out = "hello"
# Part C:
do.args = function(f){
#intialize the arguments of myfun in the parent environment
???
}
The function myfun is a trivial example of a bigger problem: I often have a complicated function with many arguments. To efficiently write and debug such a function, I find it useful to initialize the arguments of the function, and 'step through' the function line-by-line. Initializing the arguments, as in Part B above, is somewhat a hassle, when there are lots of arguments, and I would prefer to have a function as in Part C, which takes only the string myfun as it arguments and produces the same effect as running Part B in the current environment.
This only works for functions where all the arguments are defined. In other words, myfun has to have a value for a defined in the function.
some.func <- function(infunc){
forms <- formals(infunc)
for(i in 1:length(forms)){
assign(names(forms)[i],forms[[i]],envir=globalenv())
}
}
You could add a qualifier to deal with the variables that do not have default values, but it may not work in all examples. In this example I defined all missing variables to NA - and you could change the definition. Note: assigning the missing variables to NULL will not work.
some.func <- function(infunc){
forms <- formals(infunc)
for(i in 1:length(forms)){
if(class(forms[[i]])=="name") forms[[i]] <- NA
assign(names(forms)[i],forms[[i]],envir=globalenv())
}
}
You could also adjust the function and simply skip assigning the missing variables by using next after the if statement rather than defining the missing variables to NA, or some other value. The next example:
some.func <- function(infunc){
forms <- formals(infunc)
for(i in 1:length(forms)){
if(class(forms[[i]])=="name") next
assign(names(forms)[i],forms[[i]],envir=globalenv())
}
}
If you want to reassign formal arguments there is a formals<- function. By default the environment in which it does the assignment is the same as that in which it was created, bu that could be changed. See ?formals and ?alist
formals(myfun) <- alist(a=,b=4, out="not awake")
myfun
#------------------
function (a, b = 4, out = "not awake")
{
if (a > b)
print(out)
return(a - b)
You need to use alist with the argument of the form a= if you want the default to be missing.
}

Resources