Trouble Passing on an Argument to Function Within Own Function

Trouble passing on an argument to function within own function

When calling functions within functions that depend on evaluating names within a data frame, I use do.call, which evaluates its arguments before passing to the function and so makes both debugging and writing the code simpler, and I feel like I can be more sure about what it's doing. (For debugging, just use call instead of do.call, which will show what the function will try to run; the syntax is also a little different so when doing this remove the list structure within the call as well.)

(Credit to Josh O'Brien's answer here for this idea: https://stackoverflow.com/a/7668846/210673)

In this case, it would look like this:

test.fun <- function(x, data, event){
require(crrstep)
select.mod <- do.call("crrstep",
list(formula=x, etype=substitute(event), failcode=1, cencode=0,
data=as.name("data"), direction = "backward", criterion = "AIC",
crr.object = TRUE, trace = FALSE))
print(select.mod)
}

test.fun(x=formula1, data=testdata, event=fstatus)

The substitute(event) tells it to use the name that was given to the function, not the name event. The as.name("data") tells it to look for data within the function instead of passing the actual data frame. Another option is substitute(data) which will look for the actual data frame you have.

an example using lm

Here's an example of very similar behavior using lm and the weights argument:

Here's an example data set and the call to lm, not within another function. I print the call element of the response to see what it actually did.

> set.seed(5)
> dd <- data.frame(x=1:10,y=round(rnorm(10,mean=10),1), z=round(runif(10,1,4),1))
> lm(y~x, weights=z, data=dd)$call
lm(formula = y ~ x, data = dd, weights = z)

The natural way, which doesn't work because it's looking for w in the data frame:

> f1 <- function(f,w,d){
+ lm(formula=f,weights=w, data=d)
+ }
> f1(y~x, z, dd)
Error in eval(expr, envir, enclos) : object 'w' not found

One can build the call with strings; this is a little more straightforward:

> f2 <- function(f,w,d){
+ do.call("lm", list(formula=as.formula(f), weights=as.name(w), data=as.name(d)))
+ }
> f2("y~x", "z", "dd")$call
lm(formula = y ~ x, data = dd, weights = z)

Or one can use substitute; here I'm calling the function on my actual data set dd, not the d within the function. This might be useful later if I want to use update.

> f3 <- function(f,w,d){
+ do.call("lm", list(formula=f, weights=substitute(w), data=substitute(d)))
+ }
> f3(y~x, z, dd)$call
lm(formula = y ~ x, data = dd, weights = z)

But I could also use d within the function; this time notice that data = d in the call instead of data = dd.

> f4 <- function(f,w,d){
+ do.call("lm", list(formula=f, weights=substitute(w), data=as.name("d")))
+ }
> f4(y~x, z, dd)$call
lm(formula = y ~ x, data = d, weights = z)

It works to put in the actual data frame as well, but the call is longer. This however, might be desired if you're changing the data frame programatically before each call and want to have a record of what that data frame is. (My preference, though, would be to save that data frame in a more explicit way, if you really do want it later.)

> f5 <- function(f,w,d){
+ do.call("lm", list(formula=f, weights=substitute(w), data=d))
+ }
> f5(y~x, z, dd)$call
lm(formula = y ~ x, data = list(x = 1:10, y = c(9.2, 11.4, 8.7,
10.1, 11.7, 9.4, 9.5, 9.4, 9.7, 10.1), z = c(3.7, 3.2, 1.6, 1.7,
1.4, 2.4, 2.3, 3.9, 1.4, 3.9)), weights = z)

One more to show that you can't just use substitute without do.call as the substitute is executed within the call to lm.

> f6 <- function(f,w,d){
+ lm(formula=f,weights=substitute(w), data=d)
+ }
> f6(y~x, z, dd)
Error in model.frame.default(formula = f, data = d, weights = substitute(w), :
invalid type (symbol) for variable '(weights)'

Problem passing arguments to called functions in R

In my experience, this issue can often be solved by pulling the arguments into the namespace like so (untested):

fun_c <- function(...){
with(list(...), {
fa <- fun_a(x = x, y = y1)
fb <- fun_b(x = x, y = y2)
paste(fa, fb)
})
}

Pass arguments into function within a function

Try three dots instead of four, and add the ellipsis argument to the top level function:

myfunction <- function (dataframe, Colv = NA, ...) { 
matrix <- as.matrix (dataframe)
out <- heatmap(matrix, Colv = Colv, ...)
return(out)
}

Passing arguments to a function which is called by another function by its name in R

Assuming the inputs fun1, x, fun2 and args shown below the last line runs fun1.

fun1 <- function(x, fn, ...) fn(x) + fn(...)
x <- 3:4
fun2 <- sum
args <- list(1, 2)

do.call("fun1", c(list(x, fun2), args))
## [1] 10

Passing a function pointer with it's own parameters in C

Parameters are not passed. It is arguments that are passed.

So this function declaration

void runner(void (* function)(int in)){
(*function)(in);
}

has only one parameter: a pointer to a function, But if you want to call the pointed function that expects an argument then you need to supply an argument.

In this declaration of a function pointer

void (* function)(int in)

the function parameter in has the function prototype scope..

You may declare the function parameter without its identifier like

void (* function)(int)

So you have to declare the function with two parameters like

void runner(void (* function)(int), int in ){
function(in);
}

Pay attention to that to dereference the pointer to function is redundant.

All these calls as for example

( *function )( int );

or

( *****function )( in );

are equivalent to

function( in );

R pass further argument to function

I'm not entirely sure I understand you, but I think this is what you want

myFunction <- function(l, ...){
value <- lapply(l, function(x){
log(x, ...)
})
return(value)
}

Then you can run it (for example)

myFunction(l = myl, base = exp(100))

Passing the Data Argument in R User Defined Functions

Since you are using tidyverse functions, it would make sense to use tidy evaulation for this type of task. For this function you could do

test_corr <- function(data, x, y) {
quo( cor({{x}}, {{y}}) ) %>%
rlang::eval_tidy(data=data)
}

test_corr(df, x, y)

First we make a quosure to build the expression you want to evaluate and we use the {{ }} (embrace) syntax to insert the variable names you pass in to the function into the expression. We then evaluate that quosure in the context of the data.frame you supply with eval_tidy.

You might also be interested in the tidyselect package vignette where more options are discussed.



Related Topics



Leave a reply



Submit