I want to do.call
an (exported) function from a package and need to specify the package and function in the what
argument as a character string (i.e., when the package is not loaded into my environment or there is a potential function name conflict).
The function name is a character string like "lme4::lmer"
which specifies both the package and the function.
For example, to conditionally call a function (similar to this question):
FUN = if(TRUE) {
"lme4::lmer"
} else {
"nlme::nmle"
}
args.list = list(Reaction ~ Days + (Days | Subject),
quote(lme4::sleepstudy))
do.call(what=FUN, args=args.list)
# Error in `lme4::lmer`(Reaction ~ Days + (Days | Subject), lme4::sleepstudy) :
# could not find function "lme4::lmer"
Other ways work but are not what I need:
# Load the package and use only the function string
library(lme4)
do.call("lmer", ...)
# Or calling the function directly:
lme4::lmer(...)
You can't include ::
in the string because ::
is a function. That string isn't evaluated and parsed. do.call
just assumes a function by that name exists. Just like ::
, $
is also a function so this doesn't work either
a<-list(f=function(x) x+1)
do.call(a$f, list(4))
# [1] 5
do.call("a$f", list(4))
# Error in do.call("a$f", list(4)) : could not find function "a$f"
If you want to be able to find functions from namespaces, you can write a helper function that parses values when they contain ::
getfun<-function(x) {
if(length(grep("::", x))>0) {
parts<-strsplit(x, "::")[[1]]
getExportedValue(parts[1], parts[2])
} else {
x
}
}
getfun("lme4::lmer")
And this should work
do.call(getfun("lme4::lmer"), list(
Reaction ~ Days + (Days | Subject),
quote(lme4::sleepstudy)))
do.call(eval(parse(text="lme4::lmer")), ...)
eval with parse will work!
> tmp <- expand.grid(letters[1:2], 1:3, c("+", "-"))
> do.call(eval(parse(text='stringr::str_c')), c(tmp, sep = ""))
[1] "a1+" "b1+" "a2+" "b2+" "a3+" "b3+" "a1-" "b1-" "a2-" "b2-" "a3-" "b3-"
Reference: https://www.r-bloggers.com/converting-a-string-to-a-variable-name-on-the-fly-and-vice-versa-in-r/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With