library(modelsummary)
# The `modelsummary` website includes \emph{many} examples and tutorials:
# https://modelsummary.com
library(modelsummary)
# load data and estimate models
utils::data(trees)
models < list()
models[['Bivariate']] < lm(Girth ~ Height, data = trees)
models[['Multivariate']] < lm(Girth ~ Height + Volume, data = trees)
# simple table
modelsummary(models)
# statistic
modelsummary(models, statistic = NULL)
modelsummary(models, statistic = 'p.value')
modelsummary(models, statistic = 'statistic')
modelsummary(models, statistic = 'conf.int', conf_level = 0.99)
modelsummary(models, statistic = c("t = {statistic}",
"se = {std.error}",
"conf.int"))
# estimate
modelsummary(models,
statistic = NULL,
estimate = "{estimate} [{conf.low}, {conf.high}]")
modelsummary(models,
estimate = c("{estimate}{stars}",
"{estimate} ({std.error})"))
# vcov
modelsummary(models, vcov = "robust")
modelsummary(models, vcov = list("classical", "stata"))
modelsummary(models, vcov = sandwich::vcovHC)
modelsummary(models,
vcov = list(stats::vcov, sandwich::vcovHC))
modelsummary(models,
vcov = list(c("(Intercept)"="", "Height"="!"),
c("(Intercept)"="", "Height"="!", "Volume"="!!")))
# vcov with custom names
modelsummary(
models,
vcov = list("Stata Corp" = "stata",
"Newey Lewis & the News" = "NeweyWest"))
# fmt
mod < lm(mpg ~ hp + drat + qsec, data = mtcars)
modelsummary(mod, fmt = 3)
modelsummary(mod, fmt = fmt_significant(3))
modelsummary(mod, fmt = NULL)
modelsummary(mod, fmt = fmt_decimal(4))
modelsummary(mod, fmt = fmt_sprintf("%.5f"))
modelsummary(mod, fmt = fmt_statistic(estimate = 4, conf.int = 1), statistic = "conf.int")
modelsummary(mod, fmt = fmt_term(hp = 4, drat = 1, default = 2))
m < lm(mpg ~ I(hp * 1000) + drat, data = mtcars)
f < function(x) format(x, digits = 3, nsmall = 2, scientific = FALSE, trim = TRUE)
modelsummary(m, fmt = f, gof_map = NA)
# coef_rename
modelsummary(models, coef_rename = c('Volume' = 'Large', 'Height' = 'Tall'))
modelsummary(models, coef_rename = toupper)
modelsummary(models, coef_rename = coef_rename)
# coef_rename = TRUE for variable labels
datlab < mtcars
datlab$cyl < factor(datlab$cyl)
attr(datlab$hp, "label") < "Horsepower"
attr(datlab$cyl, "label") < "Cylinders"
modlab < lm(mpg ~ hp * drat + cyl, data = datlab)
modelsummary(modlab, coef_rename = TRUE)
# coef_rename: unnamed vector of length equal to the number of terms in the final table
m < lm(hp ~ mpg + factor(cyl), data = mtcars)
modelsummary(m, coef_omit = (3:4), coef_rename = c("Cyl 6", "Cyl 8"))
# coef_map
modelsummary(models, coef_map = c('Volume' = 'Large', 'Height' = 'Tall'))
modelsummary(models, coef_map = c('Volume', 'Height'))
# coef_omit: omit the first and second coefficients
modelsummary(models, coef_omit = 1:2)
# coef_omit: omit coefficients matching one substring
modelsummary(models, coef_omit = "ei", gof_omit = ".*")
# coef_omit: omit a specific coefficient
modelsummary(models, coef_omit = "^Volume$", gof_omit = ".*")
# coef_omit: omit coefficients matching either one of two substring
#modelsummary(models, coef_omit = "eirc", gof_omit = ".*")
# coef_omit: keep coefficients starting with a substring (using a negative lookahead)
#modelsummary(models, coef_omit = "^(?!Vol)", gof_omit = ".*")
# coef_omit: keep coefficients matching a substring
modelsummary(models, coef_omit = "^(?!.*ei.*pt)", gof_omit = ".*")
# shape: multinomial model
library(nnet)
multi < multinom(factor(cyl) ~ mpg + hp, data = mtcars, trace = FALSE)
# shape: term names and group ids in rows, models in columns
modelsummary(multi, shape = response ~ model)
# shape: term names and group ids in rows in a single column
modelsummary(multi, shape = term : response ~ model)
# shape: term names in rows and group ids in columns
modelsummary(multi, shape = term ~ response:model)
# shape = "rcollapse"
panels < list(
"Panel A: MPG" = list(
"A" = lm(mpg ~ hp, data = mtcars),
"B" = lm(mpg ~ hp + factor(gear), data = mtcars)),
"Panel B: Displacement" = list(
"A" = lm(disp ~ hp, data = mtcars),
"C" = lm(disp ~ hp + factor(gear), data = mtcars))
)
# shape = "cbind"
modelsummary(panels, shape = "cbind")
modelsummary(
panels,
shape = "rbind",
gof_map = c("nobs", "r.squared"))
# title
modelsummary(models, title = 'This is the title')
# title with LaTeX label (for numbering and referencing)
modelsummary(models, title = 'This is the title \\label{tab:description}', escape = FALSE)
# add_rows
rows < tibble::tribble(~term, ~Bivariate, ~Multivariate,
'Empty row', '', '',
'Another empty row', '?', '?')
attr(rows, 'position') < c(1, 3)
modelsummary(models, add_rows = rows)
# notes
modelsummary(models, notes = list('A first note', 'A second note'))
# gof_map: tribble
library(tibble)
gm < tribble(
~raw, ~clean, ~fmt,
"r.squared", "R Squared", 5)
modelsummary(models, gof_map = gm)
# gof_map: list of lists
f < function(x) format(round(x, 3), big.mark=",")
gm < list(
list("raw" = "nobs", "clean" = "N", "fmt" = f),
list("raw" = "AIC", "clean" = "aic", "fmt" = f))
modelsummary(models, gof_map = gm)
Model Summary Tables
Description
Create beautiful and customizable tables to summarize several statistical models sidebyside. This function supports dozens of statistical models, and it can produce tables in HTML, LaTeX, Word, Markdown, Typst, PDF, PowerPoint, Excel, RTF, JPG, or PNG. The appearance of the tables can be customized extensively by specifying the output
argument, and by using functions from one of the supported table customization packages: tinytable
, kableExtra
, gt
, flextable
, huxtable
, DT
. For more information, see the Details and Examples sections below, and the vignettes on the modelsummary
website: https://modelsummary.com/
Usage
modelsummary(
models,
output = "default",
fmt = 3,
estimate = "estimate",
statistic = "std.error",
vcov = NULL,
conf_level = 0.95,
exponentiate = FALSE,
stars = FALSE,
shape = term + statistic ~ model,
coef_map = NULL,
coef_omit = NULL,
coef_rename = FALSE,
gof_map = NULL,
gof_omit = NULL,
gof_function = NULL,
group_map = NULL,
add_columns = NULL,
add_rows = NULL,
align = NULL,
notes = NULL,
title = NULL,
escape = TRUE,
...
)
Arguments
models

a model, (named) list of models, or nested list of models.

output

filename or object type (character string)

fmt

how to format numeric values: integer, usersupplied function, or

estimate

a single string or a character vector of length equal to the number of models. Valid entries include any column name of the data.frame produced by

statistic

vector of strings or

vcov

robust standard errors and other manual statistics. The

conf_level

numeric value between 0 and 1. confidence level to use for confidence intervals. Setting this argument to NULL does not extract confidence intervals, which can be faster for some models.

exponentiate

TRUE, FALSE, or logical vector of length equal to the number of models. If TRUE, the estimate , conf.low , and conf.high statistics are exponentiated, and the std.error is transformed to exp(estimate)*std.error .

stars

to indicate statistical significance

shape


coef_map

character vector. Subset, rename, and reorder coefficients. Coefficients omitted from this vector are omitted from the table. The order of the vector determines the order of the table. coef_map can be a named or an unnamed character vector. If coef_map is a named vector, its values define the labels that must appear in the table, and its names identify the original term names stored in the model object: c(“hp:mpg”=“HPxM/G”) . See Examples section below.

coef_omit

integer vector or regular expression to identify which coefficients to omit (or keep) from the table. Positive integers determine which coefficients to omit. Negative integers determine which coefficients to keep. A regular expression can be used to omit coefficients, and perlcompatible "negative lookaheads" can be used to specify which coefficients to keep in the table. Examples:

coef_rename

logical, named or unnamed character vector, or function

gof_map

rename, reorder, and omit goodnessoffit statistics and other model information. This argument accepts 4 types of values:

gof_omit

string regular expression (perlcompatible) used to determine which statistics to omit from the bottom section of the table. A "negative lookahead" can be used to specify which statistics to keep in the table. Examples:

gof_function

function which accepts a model object in the model argument and returns a 1row data.frame with one custom goodnessoffit statistic per column.

group_map

named or unnamed character vector. Subset, rename, and reorder coefficient groups specified a grouping variable specified in the shape argument formula. This argument behaves like coef_map .

add_columns

a data.frame (or tibble) with the same number of rows as #’ your main table. By default, rows are appended to the bottom of the table. You can define a "position" attribute of integers to set the columns positions. See Examples section below. 
add_rows

a data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a "position" attribute of integers to set the row positions. See Examples section below. 
align

A string with a number of characters equal to the number of columns in the table (e.g.,

notes

list or vector of notes to append to the bottom of the table. 
title

string. Crossreference labels should be added with Quarto or Rmarkdown chunk options when applicable. When saving standalone LaTeX files, users can add a label such as \label{tab:mytable} directly to the title string, while also specifying escape=FALSE .

escape

boolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more finegrained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) > tinytable::format_tt(tab, j=1:5, escape=TRUE)

…

all other arguments are passed through to three functions. See the documentation of these functions for lists of available arguments.

Details
output
The modelsummary_list
output is a lightweight format which can be used to save model results, so they can be fed back to modelsummary
later to avoid extracting results again.
When a file name with a valid extension is supplied to the output
argument, the table is written immediately to file. If you want to customize your table by postprocessing it with an external package, you need to choose a different output format and saving mechanism. Unfortunately, the approach differs from package to package:

tinytable
: setoutput=“tinytable”
, postprocess your table, and use thetinytable::save_tt
function. 
gt
: setoutput=“gt”
, postprocess your table, and use thegt::gtsave
function. 
kableExtra
: setoutput
to your destination format (e.g., "latex", "html", "markdown"), postprocess your table, and usekableExtra::save_kable
function.
vcov
To use a string such as "robust" or "HC0", your model must be supported by the sandwich
package. This includes objects such as: lm, glm, survreg, coxph, mlogit, polr, hurdle, zeroinfl, and more.
NULL, "classical", "iid", and "constant" are aliases which do not modify uncertainty estimates and simply report the default standard errors stored in the model object.
Onesided formulas such as ~clusterid
are passed to the sandwich::vcovCL
function.
Matrices and functions producing variancecovariance matrices are first passed to lmtest
. If this does not work, modelsummary
attempts to take the square root of the diagonal to adjust "std.error", but the other uncertainty estimates are not be adjusted.
Numeric vectors are formatted according to fmt
and placed in brackets. Character vectors printed as given, without parentheses.
If your model type is supported by the lmtest
package, the vcov
argument will try to use that package to adjust all the uncertainty estimates, including "std.error", "statistic", "p.value", and "conf.int". If your model is not supported by lmtest
, only the "std.error" will be adjusted by, for example, taking the square root of the matrix’s diagonal.
Value
a regression table in a format determined by the output
argument.
Global Options
The behavior of modelsummary
can be modified by setting global options. For example:

options(modelsummary_model_labels = “roman”)
The rest of this section describes each of the options above.
Model labels: default column names
These global option changes the style of the default column headers:

options(modelsummary_model_labels = “roman”)

options(modelsummary_panel_labels = “roman”)
The supported styles are: "model", "panel", "arabic", "letters", "roman", "(arabic)", "(letters)", "(roman)"
The panelspecific option is only used when shape=“rbind”
Tablemaking packages
modelsummary
supports 6 tablemaking packages: tinytable
, kableExtra
, gt
, flextable
, huxtable
, and DT
. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options
function:
options(modelsummary_factory_html = ‘kableExtra’)
options(modelsummary_factory_word = ‘huxtable’)
options(modelsummary_factory_png = ‘gt’)
options(modelsummary_factory_latex = ‘gt’)
options(modelsummary_factory_latex_tabular = ‘kableExtra’)
Table themes
Change the look of tables in an automated and replicable way, using the modelsummary
theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html

modelsummary_theme_gt

modelsummary_theme_kableExtra

modelsummary_theme_huxtable

modelsummary_theme_flextable

modelsummary_theme_dataframe
Model extraction functions
modelsummary
can use two sets of packages to extract information from statistical models: the easystats
family (performance
and parameters
) and broom
. By default, it uses easystats
first and then falls back on broom
in case of failure. You can change the order of priorities or include goodnessoffit extracted by both packages by setting:
options(modelsummary_get = “easystats”)
options(modelsummary_get = “broom”)
options(modelsummary_get = “all”)
Formatting numeric entries
By default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:
options(modelsummary_format_numeric_latex = “plain”)
options(modelsummary_format_numeric_latex = “mathmode”)
A similar option can be used to display numerical entries using MathJax in HTML tables:
options(modelsummary_format_numeric_html = “mathjax”)
LaTeX preamble
When creating LaTeX via the tinytable
backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents (except when the modelsummary()
calls are cached).
\usepackage{tabularray} \usepackage{float} \usepackage{graphicx} \usepackage[normalem]{ulem} \UseTblrLibrary{booktabs} \UseTblrLibrary{siunitx} \newcommand{\tinytableTabularrayUnderline}[1]{\underline{#1}} \newcommand{\tinytableTabularrayStrikeout}[1]{\sout{#1}} \NewTableCommand{\tinytableDefineColor}[3]{\definecolor{#1}{#2}{#3}}
Parallel computation
It can take a long time to compute and extract summary statistics from certain models (e.g., Bayesian). In those cases, users can parallelize the process. Since parallelization occurs at the model level, no speedup is available for tables with a single model. Users on mac or linux can launch parallel computation using the builtin parallel
package. All they need to do is supply a mc.cores
argument which will be pushed forward to the parallel::mclapply
function:
modelsummary(model_list, mc.cores = 5)
All users can also use the future.apply
package to parallelize model summaries. For example, to use 4 cores to extract results:
library(future.apply) plan(multicore, workers = 4) options("modelsummary_future" = TRUE) modelsummary(model_list)
Note that the "multicore" plan only parallelizes under mac or linux. Windows users can use plan(multisession)
instead. However, note that the first time modelsummary()
is called under multisession can be a fair bit longer, because of extra costs in passing data to and loading required packages on to workers. Subsequent calls to modelsummary()
will often be much faster.
Some users have reported difficult to reproduce errors when using the future
package with some packages. The future
parallelization in modelsummary
can be disabled by calling:
options(“modelsummary_future” = FALSE)
References
ArelBundock V (2022). “modelsummary: Data and Model Summaries in R.” Journal of Statistical Software, 103(1), 123. .’