I am trying to fit several different models using a master function as the workhorse (each function calls this master function with the variable model
as a string and the required parameters passed via ...
)
It works fine for model = "loess"
and model = "glm"
, but fails for model = "gam"
. Specifically, do.call(model, args)
will fail unless I hardcode the function name with the namespace. But I need model
to be a variable. The same problem occurs for formalArgs
which I use to get args
. E.g (reprex) based on suggestions from similar SO questions:
model <- "mgcv::gam"
formalArgs(mgcv::gam) # Works but function is hard-coded
formalArgs(gam) # Fails
formalArgs(model) # Fails
formalArgs(eval(model)) # Fails
formalArgs(substitute(model)) # Returns NULL with warning
formalArgs(deparse(substitute(model))) # Fails
The error message is Error in get(fun, mode = "function", envir = envir) : object '"mgcv::gam"' of mode 'function' was not found
(or in the case of substitute, returns NULL).
If model
is changed to "glm"
or "loess"
, then formalArgs(model)
and formalArgs(eval(model))
work.
I think this has something to do with these two functions both being from the base stats
package while gam
is not. But how do I solve it?
The problem is that "mgcv::gam"
is text for an expression, not the name of a function. The function name is "gam"
.
To retrieve the formals, you can use formalArgs(x)
where x
is the name of a function that's available on the search list, or an actual function object.
That's why formalArgs(mgcv::gam)
works, because that expression retrieves the function object. Other ways to do it would be
model <- mgcv::gam
formalArgs(model)
#> [1] "formula" "family" "data"
#> [4] "weights" "subset" "na.action"
#> [7] "offset" "method" "optimizer"
#> [10] "control" "scale" "select"
#> [13] "knots" "sp" "min.sp"
#> [16] "H" "gamma" "fit"
#> [19] "paraPen" "G" "in.out"
#> [22] "drop.unused.levels" "drop.intercept" "nei"
#> [25] "discrete" "..."
model <- "mgcv::gam"
obj <- eval(parse(text = model))
formalArgs(obj)
#> [1] "formula" "family" "data"
#> [4] "weights" "subset" "na.action"
#> [7] "offset" "method" "optimizer"
#> [10] "control" "scale" "select"
#> [13] "knots" "sp" "min.sp"
#> [16] "H" "gamma" "fit"
#> [19] "paraPen" "G" "in.out"
#> [22] "drop.unused.levels" "drop.intercept" "nei"
#> [25] "discrete" "..."
Created on 2023-10-03 with reprex v2.0.2
Edited to add: as the comments to your question said, using formalArgs("gam")
would also work, but only if mgcv
was on the search list (because you had run library(mgcv)
to put it there, or some equivalent).