Simple, Beautiful, and Customizable Model Summaries

  output = "default",
  fmt = 3,
  estimate = "estimate",
  statistic = "std.error",
  vcov = NULL,
  conf_level = 0.95,
  stars = FALSE,
  coef_map = NULL,
  coef_omit = NULL,
  coef_rename = NULL,
  gof_map = NULL,
  gof_omit = NULL,
  add_rows = NULL,
  align = NULL,
  notes = NULL,
  title = NULL,



a model or (optionally named) list of models


filename or object type (character string)

  • Supported filename extensions: .html, .tex, .md, .txt, .png, .jpg.

  • Supported object types: "default", "html", "markdown", "latex", "data.frame", "gt", "kableExtra", "huxtable", "flextable".

  • Warning: the `output` argument cannot be used when customizing tables with external packages. See the 'Details' section below.


determines how to format numeric values

  • integer: the number of digits to keep after the period `format(round(x, fmt), nsmall=fmt)`

  • character: passed to the `sprintf` function (e.g., '%.3f' keeps 3 digits with trailing zero). See `?sprintf`

  • function: returns a formatted character string.


string or `glue` string of the estimate to display (or a vector with one string per model). Valid entries include any column name of the data.frame produced by `get_estimates(model)`. Examples:

  • "estimate"

  • "{estimate} ({std.error})stars"

  • "{estimate} [{conf.low}, {conf.high}]"


vector of strings or `glue` strings which select uncertainty statistics to report vertically below the estimate. NULL omits all uncertainty statistics.

  • "", "std.error", "statistic", "p.value", "conf.low", "conf.high", or any column name produced by: `get_estimates(model)`

  • `glue` package strings with braces, such as:

    • "{p.value} [{conf.low}, {conf.high}]"

    • "Std.Error: {std.error}"

  • Note: Parentheses are added automatically unless the string includes `glue` curly braces {}.

  • Note: To report uncertainty statistics next to coefficients, you can supply a `glue` string to the `estimate` argument.


robust standard errors and other manual statistics. The `vcov` argument accepts five types of input (see the 'Details' and 'Examples' sections below):

  • string, vector, or list of strings: "robust", "HC", "HC0", "HC1", "HC2", "HC3", "HC4", "HC4m", "HC5", "stata", or "classical" (alias "constant" or "iid").

  • formula or list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid).

  • function or list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., `stats::vcov`, `sandwich::vcovHC`).

  • list of `length(models)` variance-covariance matrices with row and column names equal to the names of your coefficient estimates.

  • a list of length(models) vectors with names equal to the names of your coefficient estimates. See 'Examples' section below.


confidence level to use for confidence intervals


to indicate statistical significance

  • FALSE (default): no significance stars.

  • TRUE: *=.1, **=.05, ***=.01

  • Named numeric vector for custom stars such as `c('*' = .1, '+' = .05)`


named character vector. Values refer to the variable names that will appear in the table. Names refer to the original term names stored in the model object, e.g. c("hp:mpg"="hp X mpg") for an interaction term. Coefficients that are omitted from this vector will be omitted from the table. The table will be ordered in the same order as this vector.


string regular expression. Omits all matching coefficients from the table using `grepl(perl=TRUE)`.


named character vector. Values refer to the variable names that will appear in the table. Names refer to the original term names stored in the model object, e.g. c("hp:mpg"="hp X mpg") for an interaction term.

  • NULL (default): the `modelsummary::gof_map` dictionary is used for formatting, and all unknown statistic are included.

  • data.frame with 3 columns named "raw", "clean", "fmt". Unknown statistics are omitted. See the 'Examples' section below.

  • list of lists, each of which includes 3 elements named "raw", "clean", "fmt". Unknown statistics are omitted. See the 'Examples section below'.


string regular expression. Omits all matching gof statistics from the table (using `grepl(perl=TRUE)`).


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.


A character string of length equal to the number of columns in the table. "lcr" means that the first column will be left-aligned, the 2nd column center-aligned, and the 3rd column right-aligned.


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




all other arguments are passed to the `tidy` and `glance` methods used to extract estimates from the model. For example, this allows users to set `exponentiate=TRUE` to exponentiate logistic regression coefficients.


a regression table in a format determined by the `output` argument.


`output` argument:

When a file name is supplied to the `output` argument, the table is written immediately to file. If you want to customize your table by post-processing it with an external package, you need to choose a different output format and saving mechanism. Unfortunately, the approach differs from package to package:

  • `gt`: set `output="gt"`, post-process your table, and use the `gt::gtsave` function.

  • `kableExtra`: set `output` to your destination format (e.g., "latex", "html", "markdown"), post-process your table, and use `kableExtra::save_kable` function.

`vcov` argument:

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.

"classical", "iid", and "constant" are aliases which do not modify uncertainty estimates and simply report the default standard errors stored in the model object.

One-sided formulas such as `~clusterid` are passed to the `sandwich::vcovCL` function.

Matrices and functions producing variance-covariance 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 "". 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.


if (FALSE) { # The `modelsummary` website includes \emph{many} examples and tutorials: # library(modelsummary) # load data and estimate models 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_level = 0.99) modelsummary(models, statistic = c("t = {statistic}", "se = {std.error}", "")) # 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"="!!"))) # coef_rename modelsummary(models, coef_map = c('Volume' = 'Large', 'Height' = 'Tall')) # coef_map modelsummary(models, coef_map = c('Volume' = 'Large', 'Height' = 'Tall')) # title modelsummary(models, title = 'This is the title') # 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: data.frame gm <- modelsummary::gof_map gof_custom$omit[gof_custom$raw == 'deviance'] <- FALSE gof_custom$fmt[gof_custom$raw == 'r.squared'] <- "%.5f" modelsummary(models, gof_map = gof_custom) # gof_map: list of lists f1 <- function(x) format(round(x, 3), big.mark=",") f2 <- function(x) format(round(x, 0), big.mark=",") gm <- list( list("raw" = "nobs", "clean" = "N", "fmt" = f2), list("raw" = "AIC", "clean" = "aic", "fmt" = f1)) modelsummary(models, fmt = f1, gof_map = gm) }