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
Warning in Install.Packages: Unable to Move Temporary Installation
Ggplot2: Flip Axes and Maintain Aspect Ratio of Data
Calculating Time Difference by Id
How to Calculate Number of Days Between Two Dates in R
How to Convert Time to Decimal
How to Merge Two Data Frames on Common Columns in R with Sum of Others
Deleting Every N-Th Row in a Dataframe
Find Locations Within Certain Lat/Lon Distance in R
In R, How to Check If Two Variable Names Reference the Same Underlying Object
Update a Column of Nas in One Data Table with the Value from a Column in Another Data Table
Si Prefixes in Ggplot2 Axis Labels
R Programming: Cache the Inverse of a Matrix
Ggpairs Plot with Heatmap of Correlation Values
Add Column Containing Data Frame Name to a List of Data Frames