# Function used in the manuscript to present summaries from 'brms' models
# in APA-formatted tables. The only obligatory argument to be supplied is
# a summary of a 'brms' model.
bayesian_model_table =
function(model_summary, show_intercept = TRUE, select_effects = NULL,
order_effects = NULL, format = NULL,
# If interaction_symbol_x = TRUE, replace double colons with
# times symbols followed by line breaks and indentation.
# Then, replace single colons with times symbols.
interaction_symbol_x = FALSE,
caption = 'Summary of the lmerTest model.') {
require(dplyr)
require(knitr)
require(tibble)
require(stringr)
require(lmerTest)
require(kableExtra)
# Create data frame
model_summary =
data.frame(Effect = rownames(model_summary$fixed),
Estimate = model_summary$fixed$Estimate,
SE = model_summary$fixed$Est.Error,
CrI_2.5 = model_summary$fixed$`l-95% CI`,
CrI_97.5 = model_summary$fixed$`u-95% CI`,
Rhat = model_summary$fixed$Rhat,
row.names = NULL)
# Process credible intervals and present both inside square brackets
model_summary$CrI_2.5 = model_summary$CrI_2.5 %>%
# Round off and keep trailing zeros
sprintf('%.2f', .) %>%
# Remove minus sign from pure zeros
sub('-0.00', '0.00', .)
model_summary$CrI_97.5 = model_summary$CrI_97.5 %>%
# Round off and keep trailing zeros
sprintf('%.2f', .) %>%
# Remove minus sign from pure zeros
sub('-0.00', '0.00', .)
model_summary$CrI_95 = paste0('[', model_summary$CrI_2.5, ', ',
model_summary$CrI_97.5, ']')
# If show_intercept = FALSE, remove it
if(isFALSE(show_intercept)) {
model_summary = model_summary %>% filter(!grepl('Intercept', Effect))
# Put 'Intercept' in parentheses
} else if(!is.null(model_summary[model_summary$Effect == 'Intercept', 'Effect'])) {
model_summary[model_summary$Effect == 'Intercept', 'Effect'] = '(Intercept)'
}
# If select_effects was supplied, apply it and order effects accordingly
if(!is.null(select_effects)) {
model_summary = model_summary %>% filter(Effect %in% select_effects) %>%
arrange(factor(Effect, levels = select_effects))
}
# If order_effects was supplied, apply order
if(!is.null(order_effects)) {
model_summary = model_summary %>%
arrange(factor(Effect, levels = order_effects))
}
# Round other values
model_summary$Estimate = model_summary$Estimate %>% as.numeric %>%
# Round off and keep trailing zeros
sprintf('%.2f', .) %>%
# Remove minus sign from pure zeros
sub('-0.00', '0.00', .)
model_summary$SE = model_summary$SE %>% as.numeric %>%
# Round off and keep trailing zeros
sprintf('%.2f', .)
model_summary$Rhat = model_summary$Rhat %>% as.numeric %>%
# Round off and keep trailing zeros
sprintf('%.2f', .)
# Order columns
model_summary = model_summary %>% select(Effect, Estimate, SE, CrI_95, Rhat)
# Right-align all columns after first one
align = c('l', 'r', 'r', 'r', 'r')
# Establish latex or HTML format: if no format supplied,
# try to obtain it from knitr, or apply HTML
if(missing(format) || is.null(format)) {
if(knitr::is_latex_output()) {
format = 'latex'
} else format = 'html'
}
# HTML format
if(format == 'html') {
# If interaction_symbol_x = TRUE, replace double colons with times
# symbols followed by line breaks and indentation. Then, replace
# single colons with times symbols.
if(interaction_symbol_x) {
model_summary$Effect = model_summary$Effect %>%
gsub('::', ' ×
', .) %>%
gsub(':', ' × ', .)
}
# Output table
model_summary %>%
# Remove header of first column and rename other headers
rename(' ' = 'Effect', 'β' = 'Estimate', 'SE' = 'SE',
'95% CrI' = 'CrI_95', '&Rcirc;' = 'Rhat') %>%
# Present table
kbl(digits = 2, booktabs = TRUE, escape = FALSE, align = align,
# Caption of the table (default unless specified)
caption = caption,
# Disable occasional line gap (https://stackoverflow.com/a/49018919/7050882)
linesep = '') %>%
# Apply nice kableExtra format
kable_styling() %>%
# Center-align header row
row_spec(0, align = 'c')
# LaTeX format
} else {
# If interaction_symbol_x = TRUE, replace double colons with times
# symbols followed by line breaks and indentation. Then, replace
# single colons with times symbols.
if(interaction_symbol_x) {
model_summary$Effect = model_summary$Effect %>%
gsub('::', ' $\\\\times$ \n \\\\hspace{0.3cm}', .) %>%
gsub(':', ' $\\\\times$ ', .)
}
model_summary$Effect = model_summary$Effect %>%
# Escape underscores to avoid error in table
str_replace_all('_', '\\\\_') %>%
# Allow line breaks in the names of the effects
# (used in the interactions)
kableExtra::linebreak(align = 'l')
# Output table
model_summary %>%
# Remove header of first column and rename other headers
rename(' ' = 'Effect', '$\\upbeta$' = 'Estimate', '$SE$' = 'SE',
'95\\% CrI' = 'CrI_95', '$\\widehat R$' = 'Rhat') %>%
# Present table
kbl(digits = 2, booktabs = TRUE, escape = FALSE, align = align,
# Caption of the table (default unless specified)
caption = caption,
# Disable occasional line gap (https://stackoverflow.com/a/49018919/7050882)
linesep = '') %>%
# Apply nice kableExtra format
kable_styling() %>%
# Center-align header row
row_spec(0, align = 'c')
}
}