rmodelsummary

modelsummary separate factor values


How can I separate factor levels from the variable name in modelsummary?

For instance:

library(modelsummary)
mod <- lm(mpg ~ factor(cyl), mtcars)
modelsummary(mod)

gives me:

+--------------+---------+
|              | (1)     |
+==============+=========+
| (Intercept)  | 26.664  |
+--------------+---------+
|              | (0.972) |
+--------------+---------+
| factor(cyl)6 | -6.921  |
+--------------+---------+
|              | (1.558) |
+--------------+---------+
| factor(cyl)8 | -11.564 |
+--------------+---------+
|              | (1.299) |
+--------------+---------+

I want:

+---------------+---------+
|               | (1)     |
+===============+=========+
| (Intercept)   | 26.664  |
+---------------+---------+
|               | (0.972) |
+---------------+---------+
| factor(cyl)_6 | -6.921  |
+---------------+---------+
|               | (1.558) |
+---------------+---------+
| factor(cyl)_8 | -11.564 |
+---------------+---------+
|               | (1.299) |
+---------------+---------+

EDIT: I prefer not to specify the variable name in coef_rename, but to have a solution that would work for any factor variable


Solution

  • The coef_rename argument of modelsummary() can take a named vector of values to rename so you can create a helper function to construct the desired names to pass to this argument. The following relies on model objects containing xlevels so won't work with models that don't.

    renamer <- function(model, sep = "_") {
      res <- mapply(\(x, y) setNames(paste(x, y[-1], sep = sep), paste0(x, y[-1])),
                    names(model$xlevels),
                    model$xlevels,
                    USE.NAMES = FALSE)
      unlist(res)
    }
    
    mod <- lm(mpg ~ factor(cyl) + vs, transform(mtcars, vs = factor(vs)))
    

    Where renamer(mod) produces:

       factor(cyl)6    factor(cyl)8             vs1 
    "factor(cyl)_6" "factor(cyl)_8"          "vs_1" 
    

    Use with modelsummary():

    modelsummary(mod, coef_rename = renamer(mod), "markdown")
    
    +---------------+---------+
    |               | (1)     |
    +===============+=========+
    | (Intercept)   | 27.290  |
    +---------------+---------+
    |               | (2.086) |
    +---------------+---------+
    | factor(cyl)_6 | -7.153  |
    +---------------+---------+
    |               | (1.724) |
    +---------------+---------+
    | factor(cyl)_8 | -12.190 |
    +---------------+---------+
    |               | (2.262) |
    +---------------+---------+
    | vs_1          | -0.689  |
    +---------------+---------+
    |               | (2.021) |
    +---------------+---------+