options(knitr.kable.NA = "") options(digits = 2) knitr::opts_chunk$set( echo = TRUE, collapse = TRUE, warning = FALSE, message = FALSE, eval = requireNamespace("gt", quietly = TRUE), comment = "#>", out.width = "100%", tidy.opts = list(width.cutoff = 100) ) # hard deps library(parameters) library(datawizard) # soft deps pkgs <- c("gt", "glmmTMB") successfully_loaded <- sapply(pkgs, requireNamespace, quietly = TRUE) if (all(successfully_loaded)) { library(glmmTMB) library(gt) } set.seed(333)
model_parameters()
and compare_parameters()
are functions that return a data frame of model summaries in a consistent way. The printed table of those summaries is formatted to make the output more readable and removes or collapses redundant columns, to get a compact and yet comprehensive summary table. (N.B. for developers: the function standardize_names()
standardizes the column names, so column names are consistent and the same for any model object, also in broom style, which makes it easy to build your packages on top of the parameters package.)
The default print-methods for model_parameters()
and compare_parameters()
allows the user to modify the layout and style of the output.
In the following examples for model_parameters()
, which returns tabular output for single models, are shown.
By default, the argument pretty_names
is TRUE
, meaning that parameter names are formatted to make them more "human readable", i.e. factor levels are separated from the variable names, interactions are denoted by *
etc.
library(parameters) data(iris) model <- lm(Sepal.Length ~ Species * Petal.Length, data = iris) model_parameters(model) mp <- model_parameters(model) print(mp, pretty_names = FALSE)
If data is labelled, pretty_names = "labels"
will use variable and value labels as pretty names. If data is not labelled, default pretty names will be used.
data(efc, package = "datawizard") model <- lm(neg_c_7 ~ e42dep + c172code, data = efc) # default printing model_parameters(model) # using value and variable labels mp <- model_parameters(model) print(mp, pretty_names = "labels")
Using summary
, or the select
argument via the print()
method allows for a more compact table, in case not all information is required. summary()
will return the coefficient, confidence intervals and p-values. select
allows to select specific columns only.
data(iris) model <- lm(Sepal.Length ~ Species * Petal.Length, data = iris) result <- model_parameters(model) # Coefficients, CI and p summary(result) # Parameter name, SE and p print(result, select = c("Parameter", "SE", "p"))
The select
argument can also be used for a more customized output. See examples below for compare_parameters()
.
Again by default, the argument split_components
is TRUE
, which means that models with multiple components like fixed and random effects, count and zero-inflated part etc. are split into separate tables in the output.
library(glmmTMB) data("Salamanders") model <- glmmTMB(count ~ spp + mined + (1 | site), ziformula = ~ spp + mined, family = nbinom2(), data = Salamanders ) model_parameters(model)
Redundant columns are removed. The related model component is shown as table header. However, you can also return a single table:
mp <- model_parameters(model) print(mp, split_component = FALSE)
A model summary can be added to the table when summary = TRUE
in the call to model_parameters()
:
model <- lm(Sepal.Length ~ Species * Petal.Length, data = iris) model_parameters(model, summary = TRUE)
Sometimes, it can be helpful to include the reference level of categorical predictors in the table. This can be done by setting include_reference = TRUE
(either directly in model_parameters()
or in the print()
method). Since the reference level is not a parameter, it is shown in a separate row, with 0
for the coefficient and blank cells for the remaining columns.
model <- lm(Sepal.Length ~ Petal.Length + Species, data = iris) model_parameters(model, include_reference = TRUE)
digits
changes the digits for coefficients, standard errors and statistics. ci_digits
and p_digits
are especially for the confidence intervals and p-values.
model <- lm(Sepal.Length ~ Species, data = iris) model_parameters(model, digits = 4)
p-values can be displayed in exact, scientific notation if required.
model_parameters(model, p_digits = "scientific")
By default, the width of table columns is set to the minimum required width. This works well for models that produce just one table. However, for models with multiple components, where each component is shown as separate table, columns are possibly no longer aligned across tables. See the following example from a zero-inflated mixed model that has three components (fixed count, fixed zero-inflated, random effects):
data("Salamanders") # we create very long parameter names for this predictor here levels(Salamanders$spp) <- paste("long", levels(Salamanders$spp)) model <- glmmTMB( count ~ spp + mined + (1 | site), ziformula = ~mined, family = poisson(), data = Salamanders ) # default printing model_parameters(model)
The column_width
argument can be used to either define the width of specific columns, or to fix column widths of the same columns across tables to have the same width. In the latter case, use column_width = "fixed"
in the print()
method.
mp <- model_parameters(model) print(mp, column_width = "fixed")
If column_width
is a named vector, names are matched against column names, and those columns gain the specified minimum width.
print(mp, column_width = c(SE = 8, `95% CI` = 12, p = 7))
The groups
argument can be used to group parameters in the table. groups
must be a named list, where the names of the list elements equal the header of each group, while the values of the list elements equal the parameter names, or the position of the parameters in the table (data frame).
In the following example, we see the names of the parameters in the Parameter
column, while the rownumbers indicate their position.
data(mtcars) mtcars$cyl <- as.factor(mtcars$cyl) mtcars$gear <- as.factor(mtcars$gear) model <- lm(mpg ~ hp + gear * vs + cyl + drat, data = mtcars) # don't select "Intercept" parameter mp <- model_parameters(model, drop = "^\\(Intercept") # inspect data frame as.data.frame(mp)
Now we create a group named "Engine"
, which encompasses the parameters "cyl6"
, "cyl8"
, "vs"
and "hp"
. The "Interactions"
group includes "gear4:vs"
and "gear5:vs"
. The group "controls"
has the parameters from rows 2, 3 and 7.
Note that the parameters in the table summary are re-ordered according to the order specified in groups
.
# group parameters, either by parameter name or position print(mp, groups = list( Engine = c("cyl6", "cyl8", "vs", "hp"), Interactions = c("gear4:vs", "gear5:vs"), Controls = c(2, 3, 7) )) # gear 4 and 5, drat
If you prefer tables without vertical borders, use the sep
argument to define the string that is used as border-separator. This argument is passed down to insight::export_table()
.
# group parameters, either by parameter name or position print(mp, sep = " ", groups = list( Engine = c("cyl6", "cyl8", "vs", "hp"), Interactions = c("gear4:vs", "gear5:vs"), Controls = c(2, 3, 7) ) )
compare_parameters()
(or its alias compare_models()
) allows to create tables for multiple models, aligned side by side.
By default, estimates and confidence intervals are shown.
data(iris) lm1 <- lm(Sepal.Length ~ Species, data = iris) lm2 <- lm(Sepal.Length ~ Species + Petal.Length, data = iris) lm3 <- lm(Sepal.Length ~ Species * Petal.Length, data = iris) compare_parameters(lm1, lm2, lm3)
By default, estimates and confidence intervals are shown. Using select
allows us to create different output, e.g. standard errors instead of confidence intervals, or including p-values.
compare_parameters(lm1, lm2, lm3, select = "se_p")
The select
argument also has a basic support for glue-like syntax, which lets you layout model elements in a very flexible way. Following tokens are replaced by the related summary coefficients or statistics:
{estimate}
(or {coefficient}
or {coef}
): coefficient{se}
(or {std.error}
or {standard error}
): standard error{ci_low}
and {ci_high}
: lower/upper confidence interval limits{p}
(or {pval}
or {p.value}
): p-values{stars}
: significant stars for p-valuesNote that you have to add parentheses manually, e.g. around confidence intervals.
# estimates, p-stars and standard error in parentheses compare_parameters(lm1, lm2, lm3, select = "{estimate}{stars} ({se})") # estimates, CI, p and stars compare_parameters(lm1, lm2, lm3, select = "{estimate} ({ci_low}, {ci_high}), p={p}{stars}")
select
also works for model_parameters()
, however, it's necessary to call this argument via the print()
method:
# estimates, p-stars and CI in parentheses result <- model_parameters(lm3) print(result, select = "{estimate}{stars} ({ci})")
The column names for the models are by default the objects' names. You can define own names using the column_names
argument.
compare_parameters( lm1, lm2, lm3, column_names = c("First Model", "Second Model", "Third Model") )
For models with multiple components, like mixed models with fixed and random effects, or models with count- and zero-inflation parts, using arguments effects = "all"
and/or component = "all"
prints separate tables for each model component.
library(glmmTMB) data("fish") m0 <- glm(count ~ child + camper, data = fish, family = poisson()) m1 <- glmmTMB( count ~ child + camper + (1 | persons) + (1 | ID), data = fish, family = poisson() ) m2 <- glmmTMB( count ~ child + camper + zg + (1 | ID), ziformula = ~ child + (1 | persons), data = fish, family = truncated_poisson() ) compare_parameters(m0, m1, m2, effects = "all", component = "all")
For such tables, they usually become clearer when the columns per model are aligned to a fixed width. You can do this using column_width = "fixed"
.
cp <- compare_parameters(m0, m1, m2, effects = "all", component = "all") print(cp, column_width = "fixed")
Grouping parameters works for compare_parameters()
in the same way as shown above for model_parameters()
.
Note: By default, the interaction mark is ×
, not *
(see also section on global options in this vignette). Since parameter names in compare_parameters()
are already formatted before printing, as.data.frame(cp)$Parameter
will probably return special unicode characters that you need to take care of in the groups
argument (unless you use numeric indices).
lm1 <- lm(Sepal.Length ~ Species + Petal.Length, data = iris) lm2 <- lm(Sepal.Width ~ Species * Petal.Length, data = iris) # remove intercept cp <- compare_parameters(lm1, lm2, drop = "^\\(Intercept") # look at parameters names, to know their names for "groups" argument as.data.frame(cp)$Parameter # note the unicode char as interaction mark # create groups. Interactions only present in 2nd model print(cp, groups = list( Species = c( "Species (versicolor)", "Species (virginica)" ), Interactions = c( "Species (versicolor) × Petal Length", # note the unicode char! "Species (virginica) × Petal Length" ), Controls = "Petal Length" ))
For very wide tables that cannot be displayed properly, you can use the table_width
argument in the print()
method to split tables into multiple parts. table_width
can be a numeric value, or "auto"
, indicating the width of the complete table. If table_width = "auto"
and the table is wider than the current available width (i.e. line length) of the console (or any other source for textual output, like markdown files), the table is split into multiple parts. Else, if table_width
is numeric and table rows are wider than table_width
, the table is split into multiple parts.
data(iris) lm1 <- lm(Sepal.Length ~ Species, data = iris) lm2 <- lm(Sepal.Length ~ Species + Petal.Length, data = iris) lm3 <- lm(Sepal.Length ~ Species * Petal.Length, data = iris) lm4 <- lm(Sepal.Length ~ Species * Petal.Length + Petal.Width, data = iris) # very wide table compare_parameters(lm1, lm2, lm3, lm4) # table split into two parts tab <- compare_parameters(lm1, lm2, lm3, lm4) print(tab, table_width = 80)
The print_md()
as well as print_html()
functions can be used to create markdown (for knitting to PDF or Word) and HTML tables.
Meanwhile, there are a lot of additional packages that allow users to have even more flexibility regarding table layouts. One package we can recommend is the modelsummary package.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.