Search code examples
rfactor-analysismodelsummary

How to use R package modelsummary to produce a factanal summary table


The modelsummary::supported_models() includes factanal objects, to purportedly produce a summary table of a factor analysis model.

However, the following two attempts fail

library(modelsummary)
library(tidyverse)

iris %>% 
  select(-Species) %>% 
  factanal(factors = 1) %>% 
  modelsummary()

iris %>% 
  select(-Species) %>% 
  factanal(factors = 1) %>% 
  tidy %>% 
  modelsummary()

How do I produce a summary table of a factor analysis fit (ie eventually making a LaTeX object)?


Solution

  • This one is kind of tricky because broom::tidy() does not return a data frame with a term column. So you have two basic options.

    library(modelsummary)
    library(tinytable)
    library(broom)
    
    mod <- factanal(mtcars, factors = 2)
    

    Option 1: modelsummary magic

    Define a custom class and extractor for your model:

    class(mod) <- c("custom", class(mod))
    
    tidy.custom <- function(x, ...) {
      out <- broom:::tidy.factanal(x, ...)
      colnames(out)[colnames(out) == "variable"] = "term"
      return(out)
    }
    
    modelsummary(mod,
      estimate = "uniqueness",
      output = "tinytable",
      statistic = c("fl1", "fl2"),
      shape = term ~ statistic) |> print("markdown")
    
    # +----------------+------------------+--------+--------+
    # |                | (1)                                |
    # +----------------+------------------+--------+--------+
    # |                | Est.             | fl1    | fl2    |
    # +================+==================+========+========+
    # | mpg            | 0.167            | 0.686  | -0.602 |
    # +----------------+------------------+--------+--------+
    # | cyl            | 0.070            | -0.629 | 0.731  |
    # +----------------+------------------+--------+--------+
    # | disp           | 0.096            | -0.730 | 0.609  |
    # +----------------+------------------+--------+--------+
    # | hp             | 0.143            | -0.337 | 0.862  |
    # +----------------+------------------+--------+--------+
    # | drat           | 0.298            | 0.807  | -0.225 |
    # +----------------+------------------+--------+--------+
    # | wt             | 0.168            | -0.810 | 0.420  |
    # +----------------+------------------+--------+--------+
    # | qsec           | 0.150            | -0.162 | -0.908 |
    # +----------------+------------------+--------+--------+
    # | vs             | 0.256            | 0.291  | -0.812 |
    # +----------------+------------------+--------+--------+
    # | am             | 0.171            | 0.907  | 0.081  |
    # +----------------+------------------+--------+--------+
    # | gear           | 0.246            | 0.860  | 0.125  |
    # +----------------+------------------+--------+--------+
    # | carb           | 0.386            | 0.031  | 0.783  |
    # +----------------+------------------+--------+--------+
    # | Num.Obs.       | 32               |        |        |
    # +----------------+------------------+--------+--------+
    # | n.factors      | 2                |        |        |
    # +----------------+------------------+--------+--------+
    # | total.variance | 0.80459022172898 |        |        |
    # +----------------+------------------+--------+--------+
    # | n              | 32               |        |        |
    # +----------------+------------------+--------+--------+
    # | method         | mle              |        |        |
    # +----------------+------------------+--------+--------+
    

    Option 2: broom + tinytable

    broom can extract info from the model as a data.frame, then use tinytable to create a table:

    s <- tidy(mod)
    tt(s, digits = 2)
    
    term uniqueness fl1 fl2
    mpg 0.167 0.686 -0.602
    cyl 0.07 -0.629 0.731
    disp 0.096 -0.73 0.609
    hp 0.143 -0.337 0.862
    drat 0.298 0.807 -0.225
    wt 0.168 -0.81 0.42
    qsec 0.15 -0.162 -0.908
    vs 0.256 0.291 -0.812
    am 0.171 0.907 0.081
    gear 0.246 0.86 0.125
    carb 0.386 0.031 0.783