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.

Summaries for a single model

In the following examples for model_parameters(), which returns tabular output for single models, are shown.

Pretty parameter names formatting

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)
#> Parameter                           | Coefficient |   SE |         95% CI | t(144) |      p
#> -------------------------------------------------------------------------------------------
#> (Intercept)                         |        4.21 | 0.41 | [ 3.41,  5.02] |  10.34 | < .001
#> Species [versicolor]                |       -1.81 | 0.60 | [-2.99, -0.62] |  -3.02 | 0.003 
#> Species [virginica]                 |       -3.15 | 0.63 | [-4.41, -1.90] |  -4.97 | < .001
#> Petal Length                        |        0.54 | 0.28 | [ 0.00,  1.09] |   1.96 | 0.052 
#> Species [versicolor] * Petal Length |        0.29 | 0.30 | [-0.30,  0.87] |   0.97 | 0.334 
#> Species [virginica] * Petal Length  |        0.45 | 0.29 | [-0.12,  1.03] |   1.56 | 0.120

mp <- model_parameters(model)
print(mp, pretty_names = FALSE)
#> Parameter                      | Coefficient |   SE |         95% CI | t(144) |      p
#> --------------------------------------------------------------------------------------
#> (Intercept)                    |        4.21 | 0.41 | [ 3.41,  5.02] |  10.34 | < .001
#> Speciesversicolor              |       -1.81 | 0.60 | [-2.99, -0.62] |  -3.02 | 0.003 
#> Speciesvirginica               |       -3.15 | 0.63 | [-4.41, -1.90] |  -4.97 | < .001
#> Petal.Length                   |        0.54 | 0.28 | [ 0.00,  1.09] |   1.96 | 0.052 
#> Speciesversicolor:Petal.Length |        0.29 | 0.30 | [-0.30,  0.87] |   0.97 | 0.334 
#> Speciesvirginica:Petal.Length  |        0.45 | 0.29 | [-0.12,  1.03] |   1.56 | 0.120

Splitting model components

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)
#> # Fixed Effects (Count Model)
#> 
#> Parameter   | Log-Mean |   SE |        95% CI |     z |      p
#> --------------------------------------------------------------
#> (Intercept) |    -0.61 | 0.41 | [-1.40, 0.18] | -1.51 | 0.132 
#> spp [PR]    |    -0.96 | 0.64 | [-2.23, 0.30] | -1.50 | 0.134 
#> spp [DM]    |     0.17 | 0.24 | [-0.29, 0.63] |  0.73 | 0.468 
#> spp [EC-A]  |    -0.39 | 0.34 | [-1.06, 0.28] | -1.13 | 0.258 
#> spp [EC-L]  |     0.49 | 0.24 | [ 0.02, 0.96] |  2.05 | 0.041 
#> spp [DES-L] |     0.59 | 0.23 | [ 0.14, 1.04] |  2.59 | 0.010 
#> spp [DF]    |    -0.11 | 0.24 | [-0.59, 0.36] | -0.46 | 0.642 
#> mined [no]  |     1.43 | 0.37 | [ 0.71, 2.15] |  3.90 | < .001
#> 
#> # Fixed Effects (Zero-Inflated Model)
#> 
#> Parameter   | Log-Odds |   SE |         95% CI |     z |      p
#> ---------------------------------------------------------------
#> (Intercept) |     0.91 | 0.63 | [-0.32,  2.14] |  1.45 | 0.147 
#> spp [PR]    |     1.16 | 1.33 | [-1.45,  3.78] |  0.87 | 0.384 
#> spp [DM]    |    -0.94 | 0.80 | [-2.51,  0.63] | -1.17 | 0.241 
#> spp [EC-A]  |     1.04 | 0.71 | [-0.36,  2.44] |  1.46 | 0.144 
#> spp [EC-L]  |    -0.56 | 0.73 | [-1.99,  0.86] | -0.77 | 0.439 
#> spp [DES-L] |    -0.89 | 0.75 | [-2.37,  0.58] | -1.19 | 0.236 
#> spp [DF]    |    -2.54 | 2.18 | [-6.82,  1.74] | -1.16 | 0.244 
#> mined [no]  |    -2.56 | 0.60 | [-3.75, -1.38] | -4.24 | < .001
#> 
#> # Dispersion
#> 
#> Parameter   | Coefficient
#> -------------------------
#> (Intercept) |        0.41
#> 
#> # Random Effects Variances
#> 
#> Parameter            | Coefficient
#> ----------------------------------
#> SD (Intercept: site) |        0.38
#> SD (Residual)        |        1.51
#> 
#> # Random Effects (Zero-Inflated Model)
#> 
#> Parameter     | Coefficient
#> ---------------------------
#> SD (Residual) |        1.51

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)
#> # Fixed Effects
#> 
#> Parameter            | Coefficient |   SE |         95% CI |     z |      p | Effects |     Component
#> -----------------------------------------------------------------------------------------------------
#> (Intercept)          |       -0.61 | 0.41 | [-1.40,  0.18] | -1.51 | 0.132  |   fixed |   conditional
#> spp [PR]             |       -0.96 | 0.64 | [-2.23,  0.30] | -1.50 | 0.134  |   fixed |   conditional
#> spp [DM]             |        0.17 | 0.24 | [-0.29,  0.63] |  0.73 | 0.468  |   fixed |   conditional
#> spp [EC-A]           |       -0.39 | 0.34 | [-1.06,  0.28] | -1.13 | 0.258  |   fixed |   conditional
#> spp [EC-L]           |        0.49 | 0.24 | [ 0.02,  0.96] |  2.05 | 0.041  |   fixed |   conditional
#> spp [DES-L]          |        0.59 | 0.23 | [ 0.14,  1.04] |  2.59 | 0.010  |   fixed |   conditional
#> spp [DF]             |       -0.11 | 0.24 | [-0.59,  0.36] | -0.46 | 0.642  |   fixed |   conditional
#> mined [no]           |        1.43 | 0.37 | [ 0.71,  2.15] |  3.90 | < .001 |   fixed |   conditional
#> (Intercept)          |        0.91 | 0.63 | [-0.32,  2.14] |  1.45 | 0.147  |   fixed | zero_inflated
#> sppPR                |        1.16 | 1.33 | [-1.45,  3.78] |  0.87 | 0.384  |   fixed | zero_inflated
#> sppDM                |       -0.94 | 0.80 | [-2.51,  0.63] | -1.17 | 0.241  |   fixed | zero_inflated
#> sppEC-A              |        1.04 | 0.71 | [-0.36,  2.44] |  1.46 | 0.144  |   fixed | zero_inflated
#> sppEC-L              |       -0.56 | 0.73 | [-1.99,  0.86] | -0.77 | 0.439  |   fixed | zero_inflated
#> sppDES-L             |       -0.89 | 0.75 | [-2.37,  0.58] | -1.19 | 0.236  |   fixed | zero_inflated
#> sppDF                |       -2.54 | 2.18 | [-6.82,  1.74] | -1.16 | 0.244  |   fixed | zero_inflated
#> minedno              |       -2.56 | 0.60 | [-3.75, -1.38] | -4.24 | < .001 |   fixed | zero_inflated
#> (Intercept)          |        0.41 |      |                |       |        |   fixed |    dispersion
#> SD (Intercept: site) |        0.38 |      |                |       |        |  random |   conditional
#> SD (Residual)        |        1.51 |      |                |       |        |  random |   conditional
#> SD (Residual)        |        1.51 |      |                |       |        |  random | zero_inflated

Adding model summaries

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)
#> Parameter                           | Coefficient |   SE |         95% CI | t(144) |      p
#> -------------------------------------------------------------------------------------------
#> (Intercept)                         |        4.21 | 0.41 | [ 3.41,  5.02] |  10.34 | < .001
#> Species [versicolor]                |       -1.81 | 0.60 | [-2.99, -0.62] |  -3.02 | 0.003 
#> Species [virginica]                 |       -3.15 | 0.63 | [-4.41, -1.90] |  -4.97 | < .001
#> Petal Length                        |        0.54 | 0.28 | [ 0.00,  1.09] |   1.96 | 0.052 
#> Species [versicolor] * Petal Length |        0.29 | 0.30 | [-0.30,  0.87] |   0.97 | 0.334 
#> Species [virginica] * Petal Length  |        0.45 | 0.29 | [-0.12,  1.03] |   1.56 | 0.120 
#> 
#> Model: Sepal.Length ~ Species * Petal.Length (150 Observations)
#> Residual standard deviation: 0.336 (df = 144)
#> R2: 0.840; adjusted R2: 0.835

Changing number of digits

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)
#> Parameter            | Coefficient |     SE |       95% CI |  t(147) |      p
#> -----------------------------------------------------------------------------
#> (Intercept)          |      5.0060 | 0.0728 | [4.86, 5.15] | 68.7616 | < .001
#> Species [versicolor] |      0.9300 | 0.1030 | [0.73, 1.13] |  9.0328 | < .001
#> Species [virginica]  |      1.5820 | 0.1030 | [1.38, 1.79] | 15.3655 | < .001

p-values can be displayed in exact, scientific notation if required.

model_parameters(model, p_digits = "scientific")
#> Parameter            | Coefficient |   SE |       95% CI | t(147) |            p
#> --------------------------------------------------------------------------------
#> (Intercept)          |        5.01 | 0.07 | [4.86, 5.15] |  68.76 | 1.13429e-113
#> Species [versicolor] |        0.93 | 0.10 | [0.73, 1.13] |   9.03 | 8.77019e-16 
#> Species [virginica]  |        1.58 | 0.10 | [1.38, 1.79] |  15.37 | 2.21482e-32

Group parameters

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)
#>   Parameter Coefficient    SE   CI CI_low CI_high     t df_error      p
#> 1        hp      -0.062 0.021 0.95  -0.11  -0.018 -2.91       22 0.0081
#> 2     gear4       3.100 4.339 0.95  -5.90  12.098  0.71       22 0.4825
#> 3     gear5       4.798 3.478 0.95  -2.42  12.011  1.38       22 0.1816
#> 4        vs       3.183 3.790 0.95  -4.68  11.042  0.84       22 0.4100
#> 5      cyl6      -2.466 2.210 0.95  -7.05   2.116 -1.12       22 0.2764
#> 6      cyl8       1.975 5.111 0.95  -8.63  12.575  0.39       22 0.7029
#> 7      drat       2.697 2.033 0.95  -1.52   6.913  1.33       22 0.1983
#> 8  gear4:vs      -2.897 4.665 0.95 -12.57   6.778 -0.62       22 0.5410
#> 9  gear5:vs       2.588 4.537 0.95  -6.82  11.998  0.57       22 0.5741

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
#> Parameter        | Coefficient |   SE |          95% CI | t(22) |     p
#> -----------------------------------------------------------------------
#> Engine           |             |      |                 |       |      
#>   cyl [6]        |       -2.47 | 2.21 | [ -7.05,  2.12] | -1.12 | 0.276
#>   cyl [8]        |        1.97 | 5.11 | [ -8.63, 12.58] |  0.39 | 0.703
#>   vs             |        3.18 | 3.79 | [ -4.68, 11.04] |  0.84 | 0.410
#>   hp             |       -0.06 | 0.02 | [ -0.11, -0.02] | -2.91 | 0.008
#> Interactions     |             |      |                 |       |      
#>   gear [4] * vs  |       -2.90 | 4.67 | [-12.57,  6.78] | -0.62 | 0.541
#>   gear [5] * vs  |        2.59 | 4.54 | [ -6.82, 12.00] |  0.57 | 0.574
#> Controls         |             |      |                 |       |      
#>   gear [4]       |        3.10 | 4.34 | [ -5.90, 12.10] |  0.71 | 0.482
#>   gear [5]       |        4.80 | 3.48 | [ -2.42, 12.01] |  1.38 | 0.182
#>   drat           |        2.70 | 2.03 | [ -1.52,  6.91] |  1.33 | 0.198

Summaries for multiple models

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)
#> Parameter                           |               lm1 |                  lm2 |                  lm3
#> -----------------------------------------------------------------------------------------------------
#> (Intercept)                         | 5.01 (4.86, 5.15) |  3.68 ( 3.47,  3.89) |  4.21 ( 3.41,  5.02)
#> Species (versicolor)                | 0.93 (0.73, 1.13) | -1.60 (-1.98, -1.22) | -1.81 (-2.99, -0.62)
#> Species (virginica)                 | 1.58 (1.38, 1.79) | -2.12 (-2.66, -1.58) | -3.15 (-4.41, -1.90)
#> Petal Length                        |                   |  0.90 ( 0.78,  1.03) |  0.54 ( 0.00,  1.09)
#> Species (versicolor) * Petal Length |                   |                      |  0.29 (-0.30,  0.87)
#> Species (virginica) * Petal Length  |                   |                      |  0.45 (-0.12,  1.03)
#> -----------------------------------------------------------------------------------------------------
#> Observations                        |               150 |                  150 |                  150

Changing style of column output

By default, estimates and confidence intervals are shown. Using style allows us to create different output, e.g. standard errors instead of confidence intervals, or including p-values.

compare_parameters(lm1, lm2, lm3, style = "se_p")
#> Parameter                           |            lm1 |             lm2 |             lm3
#> ----------------------------------------------------------------------------------------
#> (Intercept)                         | 5.01*** (0.07) |  3.68*** (0.11) |  4.21*** (0.41)
#> Species (versicolor)                | 0.93*** (0.10) | -1.60*** (0.19) |  -1.81** (0.60)
#> Species (virginica)                 | 1.58*** (0.10) | -2.12*** (0.27) | -3.15*** (0.63)
#> Petal Length                        |                |  0.90*** (0.06) |     0.54 (0.28)
#> Species (versicolor) * Petal Length |                |                 |     0.29 (0.30)
#> Species (virginica) * Petal Length  |                |                 |     0.45 (0.29)
#> ----------------------------------------------------------------------------------------
#> Observations                        |            150 |             150 |             150

Defining column names

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")
)
#> Parameter                           |       First Model |         Second Model |          Third Model
#> -----------------------------------------------------------------------------------------------------
#> (Intercept)                         | 5.01 (4.86, 5.15) |  3.68 ( 3.47,  3.89) |  4.21 ( 3.41,  5.02)
#> Species (versicolor)                | 0.93 (0.73, 1.13) | -1.60 (-1.98, -1.22) | -1.81 (-2.99, -0.62)
#> Species (virginica)                 | 1.58 (1.38, 1.79) | -2.12 (-2.66, -1.58) | -3.15 (-4.41, -1.90)
#> Petal Length                        |                   |  0.90 ( 0.78,  1.03) |  0.54 ( 0.00,  1.09)
#> Species (versicolor) * Petal Length |                   |                      |  0.29 (-0.30,  0.87)
#> Species (virginica) * Petal Length  |                   |                      |  0.45 (-0.12,  1.03)
#> -----------------------------------------------------------------------------------------------------
#> Observations                        |               150 |                  150 |                  150

Group parameters of multiple model tables

Grouping parameters works for compare_models() in the same way as shown above for model_parameters().

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
#> [1] "Species (versicolor)"                "Species (virginica)"                
#> [3] "Petal Length"                        "Species (versicolor) * Petal Length"
#> [5] "Species (virginica) * Petal Length"

# create groups. Interactions only present in 2nd model
print(cp, groups = list(Species = c("Species (versicolor)", 
                                    "Species (virginica)"),
                        Interactions = c("Species (versicolor) * Petal Length",
                                         "Species (virginica) * Petal Length"),
                        Controls = "Petal Length"))
#> Parameter                             |                  lm1 |                  lm2
#> -----------------------------------------------------------------------------------
#> Species                               |                      |                     
#>   Species (versicolor)                | -1.60 (-1.98, -1.22) | -1.69 (-2.80, -0.57)
#>   Species (virginica)                 | -2.12 (-2.66, -1.58) | -1.19 (-2.37, -0.01)
#> Interactions                          |                      |                     
#>   Species (versicolor) * Petal Length |                      | -0.01 (-0.56,  0.53)
#>   Species (virginica) * Petal Length  |                      | -0.15 (-0.69,  0.39)
#> Controls                              |                      |                     
#>   Petal Length                        |  0.90 ( 0.78,  1.03) |  0.39 (-0.13,  0.90)
#> -----------------------------------------------------------------------------------
#>   Observations                        |                  150 |                  150

More advances tables and markdown / HTML formatting

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.