0

I am trying to create a wrapper around a function for model reporting; I want some aesthetic defaults to be the same and then modify any other arguments as needed. Inspired mostly by this answer, I thought about using ellipsis as follows:

library(sjPlot)

mods <- list(lm(1 ~ 1), lm(1 ~ 1))

my_tab_model <- function(x, ...) {

  defargs <- list(show.aic = TRUE, 
                   prefix.labels = "varname", 
                   rm.terms = "Log(theta)", 
                   p.style = "asterisk", 
                   p.threshold = c(0.1, 0.05, 0.01))

  args <- list(...)

  defargs[names(args)] <- args

  do.call(tab_model, list(x, args, defargs))

  }

my_tab_model(mods, dv.labels = c("One model", "Another model"), 
             title = "mods")

But I'm getting the following error:

#> Error: $ operator is invalid for atomic vectors
Traceback:
4. .f(.x[[i]], .y[[i]], ...) 
3. purrr::map2(models, 1:length(models), function(model, i) {
    fam.info <- insight::model_info(model)
    if (insight::is_multivariate(model)) 
        fam.info <- fam.info[[1]] ... 
2. tab_model(args, show.aic = TRUE, prefix.labels = "varname", rm.terms = "Log(theta)", 
    p.style = "asterisk", p.threshold = c(0.1, 0.05, 0.01)) 
1. my_tab_model(mod, dv.labels = c("One model", "Another model"), 
    title = "mods") 

After reading around a bit, I'm still quite baffled. I thought I read somewhere that map does not accept ellipsis without some workaround; so I suspect it could have something to do with the tab_model function itself calling map to deal with its own ellipsis as its first argument. However, I can't find that source and this answer does not mention any such issues; so I'm still not quite sure what's going on.

To compound my bafflement, when I run it on the actual data, the error is different:

Error in names(models) <- unlist(lapply(match.call(expand.dots = F)$..., : 'names' attribute [74] must be the same length as the vector [4]
3. (function (..., transform, show.intercept = TRUE, show.est = TRUE, show.ci = 0.95, show.ci50 = TRUE, show.se = NULL, show.std = NULL, show.p = TRUE, show.stat = FALSE, show.df = FALSE, show.zeroinf = TRUE, show.r2 = TRUE, show.icc = TRUE, show.re.var = TRUE, show.ngroups = TRUE, ...
2. do.call(tab_model, c(x, args, defargs))
1. my_tab_model(negbin_alliance_mods, dv.labels = party_levels, title = "negbin_alliance_mods without supply")

Can I use ellipsis in this way for a function like tab_model case and if so how?

Any pointers would be greatly appreciated!

Fons MA
  • 1,142
  • 1
  • 12
  • 21
  • 1
    Can you try changing your `do.call` to `do.call(tab_model, c(list(x), args, defargs))`? – Alexis Aug 03 '19 at 08:47
  • Thank you Alexis. Sorry I was busy with other things. With your suggestion the error becomes: `Error in (function (..., transform, show.intercept = TRUE, show.est = TRUE, : formal argument "title" matched by multiple actual arguments` I don't know why that would be the case... – Fons MA Aug 13 '19 at 06:41
  • 1
    Oh, that's because `defargs[names(args)] <- args` copies everything from `args` into `defargs`, and things are duplicated if you pass both to `do.call`. You should change your strategy a bit, e.g. assign values from `defargs` to `args` only if they weren't already present in `args`, and then pass only one of the two to `do.call`. – Alexis Aug 13 '19 at 07:28
  • Ah, right; that was actually to be expected... so technically `defargs[names(args)] <- args` and then `do.call(tab_model, c(list(x), defargs))` should work? I have quickly tested it and gives me another error: `Error in attr(lbs, "category.value") <- fl : attempt to set an attribute on NULL ` ... maybe it's also obvious but I'm feeling pretty sluggish.Thanks for your help! – Fons MA Aug 13 '19 at 07:37

0 Answers0