Create a nicely-formatted table of coefficients

There are three ways that you might make a nicely-formatted table that shows your fixed effect coefficient estimates.

Examples below. In reports, it doesn’t matter which of these you use, as long as the key information (the fixed effect estimates and their significance) is there.

Example data: University job satisfaction

Let’s suppose we are studying employee job satisfaction at the university, and we want to estimate the association between pay-scale and job satisfaction, controlling for the NSS rating of departments.

We have 399 employees from 25 different departments, and we got them to fill in a job satisfaction questionnaire, and got information on what their payscale was. We have also taken information from the National Student Survey on the level of student satisfaction for each department.

Each datapoint here represents an individual employee, and these employees are grouped into departments.

variable description
NSSrating National Student Satisfaction rating for the department
dept Department name
payscale Pay scale of employee
jobsat Job satisfaction of employee
jobsat_binary Binary question of whether the employee considered themselves to be satisfied with their work (1) or not (0)
jobsat <- read_csv("https://uoepsy.github.io/data/msmr_nssjobsat.csv")

Here’s the maximal model for this data:

jobsat_mod <- lmerTest::lmer(
  jobsat ~ 1 + payscale + NSSrating + (1 + payscale | dept), 
  data = jobsat
)

We are predicting employee’s job satisfaction as a function of their pay scale and the department’s NSS rating. We’re also including by-department adjustments to the fixed intercept and to the slope over payscale.

To see where the lmerTest::lmer() bit comes from, see Get p-values for LMM coefficients.

tab_model() from sjPlot

library(sjPlot)

tab_model(jobsat_mod)
  jobsat
Predictors Estimates CI p
(Intercept) 14.53 12.56 – 16.49 <0.001
payscale 0.34 0.18 – 0.49 <0.001
NSSrating 0.43 0.17 – 0.69 0.001
Random Effects
σ2 1.04
τ00 dept 0.87
τ11 dept.payscale 0.09
ρ01 dept -0.49
ICC 0.77
N dept 25
Observations 399
Marginal R2 / Conditional R2 0.168 / 0.809


Classic and minimal, and works just fine when knitting to HTML, but fails to render properly when knitting a document to PDF.

tidy() from broom.mixed

library(broom.mixed)
library(kableExtra)

The code chunk below has the following header line, which defines the label we’ll use to refer to this table in the text:

```{r FromBroomMixed}


tidy(jobsat_mod) |>
  filter(effect=="fixed") |>
  select(-effect, -group) |>
  mutate(
    estimate = round(estimate, 2),
    std.error = round(std.error, 2)
  ) |>
  kable(
    booktabs = TRUE, 
    caption = 'This is my caption'
    # when you render to PDF (not to HTML as we are doing here), 
    # the caption will appear as "Table 1: This is my caption"
  )  
This is my caption
term estimate std.error statistic df p.value
(Intercept) 14.53 1.00 14.55 24.5 0.000
payscale 0.34 0.08 4.21 23.2 0.000
NSSrating 0.43 0.13 3.25 20.8 0.004


To refer to this table in your Rmd file, write:

Here I am cross-referencing Table \@ref(tab:FromBroomMixed).

This will appear as “Here I am cross-referencing Table 1”.

For more detail on table formatting and cross-referencing, see the DAPR1 table formatting resources.

modelsummary() from modelsummary

library(modelsummary)
modelsummary(
  models = list('Job satisfaction' = jobsat_mod),  
  # ^ in general: `list('<Dependent variable name>' = <modelname>)`
  
  fmt = fmt_statistic('estimate' = 2, 'std.error' = 2, 'conf.int' = 2, 'p.value' = 3),
  estimate = c("b" = "{estimate}"),
  statistic = c("SE" = "{std.error}", "p" = "{p.value}", "CI" = "[{conf.low}, {conf.high}]"),
  shape = term ~ statistic,
  gof_map = 'none',
  output = 'markdown',
  # ^ leave all this as-is
  
  title = "(\\#tab:FromModelSummary) This is my caption"
  # ^ best to only edit the bits outside brackets.
  # when you render to PDF (not to HTML as we are doing here), 
  # the caption will appear as "Table 2: This is my caption"
)
(#tab:FromModelSummary) This is my caption
Job satisfaction
b SE p CI
(Intercept) 14.53 1.00 0.000 [12.56, 16.49]
payscale 0.34 0.08 0.000 [0.18, 0.49]
NSSrating 0.43 0.13 0.001 [0.17, 0.69]
SD (Intercept dept) 0.93
SD (payscale dept) 0.29
Cor (Intercept~payscale dept) -0.49
SD (Observations) 1.02


In your Rmd file, write:

Here I am cross-referencing Table \@ref(tab:FromModelSummary).

This will appear as “Here I am cross-referencing Table 2”.

For more detail on table formatting and cross-referencing, see the DAPR1 table formatting resources.