I trying to extract all arguments and their default options from a function (randomForestSRC::rfsrc
) to integrate it within another function. This is what I'm doing:
> mydata <- source("https://pastebin.com/raw/bL8ZHvbt")$value
> myparams <- list(ntree = 500, seed = 333)
> time = "OS"
> event = "Death"
# prepare vars
> aux <- formals(randomForestSRC::rfsrc)[-c(1,2,32,35)] #delete arguments I gonna manually add
> diffs <- setdiff(names(aux), names(myparams))
> method.params <- c(myparams, aux[diffs])
# run function
> f <- as.formula(paste0("Surv(", time, ",", event, ") ~ ."))
> res <- do.call(randomForestSRC::rfsrc, c(list(formula = f, data = mydata), method.params))
Error in (function (formula, data, ntree = 1000, mtry = NULL, ytry = NULL, :
object 'samptype' not found
I guess the error prompts because rfsrc
's arguments format: it's not a single value but multiple options... despite of having only one as default option.
> aux$importance #default value for "importance" is "none"
c(FALSE, TRUE, "none", "permute", "random", "anti")
> str(aux)
List of 31
$ ntree : num 1000
$ nodedepth : NULL
$ splitrule : NULL
$ nsplit : num 10
$ importance : language c(FALSE, TRUE, "none", "permute", "random", "anti")
...
My question is how can I extract this only default value and not the entire string of options? Thanks in advance.
This will let you alter the defaults of the two parameters you sought to set at 500 and 333 in a new function with the same environment as the original rfsrc
. (You can do it in the original function, but that seems more dangerous.)
library(randomForestSRC)
rfsrc2 <- rfsrc
environment(rfsrc2) <- environment(rfsrc)
params <- formals(rfsrc)
myparams <- list(ntree = 500, seed = 333)
params[c("ntree","seed")] <- myparams
# more generally could have been `params[names(myparams)]` on LHS
formals(rfsrc2) <- params
str(rfsrc2)
#-------
function (formula, data, ntree = 500, mtry = NULL, ytry = NULL, nodesize = NULL, nodedepth = NULL, splitrule = NULL, nsplit = 10,
importance = c(FALSE, TRUE, "none", "permute", "random", "anti"), block.size = if (any(is.element(as.character(importance),
c("none", "FALSE")))) NULL else 10, ensemble = c("all", "oob", "inbag"), bootstrap = c("by.root", "none", "by.user"),
samptype = c("swor", "swr"), samp = NULL, membership = FALSE, sampsize = if (samptype == "swor") function(x) {
x * 0.632
} else function(x) {
x
}, na.action = c("na.omit", "na.impute"), nimpute = 1, ntime, cause, proximity = FALSE, distance = FALSE, forest.wt = FALSE,
xvar.wt = NULL, yvar.wt = NULL, split.wt = NULL, case.wt = NULL, forest = TRUE, var.used = c(FALSE, "all.trees", "by.tree"),
split.depth = c(FALSE, "all.trees", "by.tree"), seed = 333, do.trace = FALSE, statistics = FALSE, ...)
# test of "function"-ality
rfsrc2(formula=f, data=mydata)
Sample size: 100
Number of deaths: 11
Number of trees: 500
Forest terminal node size: 15
Average no. of terminal nodes: 4.464
No. of variables tried at each split: 3
Total no. of variables: 6
Resampling used to grow trees: swor
Resample size used to grow trees: 63
Analysis: RSF
Family: surv
Splitting rule: logrank *random*
Number of random split points: 10
Error rate: 58.9%
If you wanted to do that with do.call it could have been:
do.call( rfsrc2, list(formula=f, data=mydata) )
It's crucial that you not remove formula
, data
and ...
from the formals-list since they need to be there when the code in the body of the function seeks to evaluate them. I'm pretty sure you cannot just paste them back (after removing them) by using do.call
. You could of course have side-stepped the whole process by just:
do.call( rfsrc, list(formula=f, data=mydata, ntree=500, seed=333) )
.... but I got the idea you wanted methods to do surgery on a formals-list outside of the function itself.