Beautiful table-outputs: Summarizing mixed effects models #rstats
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
The current version 1.8.1 of my sjPlot package has two new functions to easily summarize mixed effects models as HTML-table: sjt.lmer
and sjt.glmer
. Both are very similar, so I focus on showing how to use sjt.lmer
here.
# load required packages library(sjPlot) # table functions library(sjmisc) # sample data library(lme4) # fitting models
Linear mixed models summaries as HTML table
The sjt.lmer
function prints summaries of linear mixed models (fitted with the lmer
function of the lme4-package) as nicely formatted html-tables. First, some sample models are fitted:
# load sample data data(efc) # prepare grouping variables efc$grp = as.factor(efc$e15relat) levels(x = efc$grp) <- get_val_labels(efc$e15relat) efc$care.level <- as.factor(rec(efc$n4pstu, "0=0;1=1;2=2;3:4=4")) levels(x = efc$care.level) <- c("none", "I", "II", "III") # data frame for fitted model mydf <- data.frame(neg_c_7 = as.numeric(efc$neg_c_7), sex = as.factor(efc$c161sex), c12hour = as.numeric(efc$c12hour), barthel = as.numeric(efc$barthtot), education = as.factor(efc$c172code), grp = efc$grp, carelevel = efc$care.level) # fit sample models fit1 <- lmer(neg_c_7 ~ sex + c12hour + barthel + (1|grp), data = mydf) fit2 <- lmer(neg_c_7 ~ sex + c12hour + education + barthel + (1|grp), data = mydf) fit3 <- lmer(neg_c_7 ~ sex + c12hour + education + barthel + (1|grp) + (1|carelevel), data = mydf)
The simplest way of producing the table output is by passing the fitted models as parameter. By default, estimates (B), confidence intervals (CI) and p-values (p) are reported. The models are named Model 1 and Model 2. The resulting table is divided into three parts:
- Fixed parts – the model’s fixed effects coefficients, including confidence intervals and p-values.
- Random parts – the model’s group count (amount of random intercepts) as well as the Intra-Class-Correlation-Coefficient ICC.
- Summary – Observations, AIC etc.
sjt.lmer(fit1, fit2)
Note that, due to WordPress-CSS, the resulting HTML-table looks different in this blog-posting compared to the usual output in R!
Model 1 | Model 2 | |||||||
B | CI | p | B | CI | p | |||
Fixed Parts | ||||||||
(Intercept) | 14.14 | 13.15 – 15.12 | <.001 | 13.75 | 12.63 – 14.87 | <.001 | ||
sex2 | 0.48 | -0.07 – 1.03 | .087 | 0.67 | 0.10 – 1.25 | .020 | ||
c12hour | 0.00 | -0.00 – 0.01 | .233 | 0.00 | -0.00 – 0.01 | .214 | ||
barthel | -0.05 | -0.06 – -0.04 | <.001 | -0.05 | -0.06 – -0.04 | <.001 | ||
education2 | 0.19 | -0.43 – 0.80 | .098 | |||||
education3 | 0.80 | 0.03 – 1.58 | .098 | |||||
Random Parts | ||||||||
N_{grp} | 8 | 8 | ||||||
ICC_{grp} | 0.022 | 0.021 | ||||||
Observations | 872 | 815 |
Customizing labels
Here is an example how to change the labels. Note that showHeaderStrings
makes the two labels on top and top left corner appear in the table.
sjt.lmer(fit1, fit2, showHeaderStrings = TRUE, stringB = "Estimate", stringCI = "Conf. Int.", stringP = "p-value", stringDependentVariables = "Response", stringPredictors = "Coefficients", stringIntercept = "Konstante", labelDependentVariables = c("Negative Impact", "Negative Impact"))
Coefficients | Response | |||||||
Negative Impact | Negative Impact | |||||||
Estimate | Conf. Int. | p-value | Estimate | Conf. Int. | p-value | |||
Fixed Parts | ||||||||
Konstante | 14.14 | 13.15 – 15.12 | <.001 | 13.75 | 12.63 – 14.87 | <.001 | ||
sex2 | 0.48 | -0.07 – 1.03 | .087 | 0.67 | 0.10 – 1.25 | .020 | ||
c12hour | 0.00 | -0.00 – 0.01 | .233 | 0.00 | -0.00 – 0.01 | .214 | ||
barthel | -0.05 | -0.06 – -0.04 | <.001 | -0.05 | -0.06 – -0.04 | <.001 | ||
education2 | 0.19 | -0.43 – 0.80 | .098 | |||||
education3 | 0.80 | 0.03 – 1.58 | .098 | |||||
Random Parts | ||||||||
N_{grp} | 8 | 8 | ||||||
ICC_{grp} | 0.022 | 0.021 | ||||||
Observations | 872 | 815 |
Custom variable labels
To change variable labels in the plot, use the labelPredictors
parameter:
sjt.lmer(fit1, fit2, labelPredictors = c("Carer's Sex", "Hours of Care", "Elder's Dependency", "Mid Educational Level", "High Educational Level"))
Model 1 | Model 2 | |||||||
B | CI | p | B | CI | p | |||
Fixed Parts | ||||||||
(Intercept) | 14.14 | 13.15 – 15.12 | <.001 | 13.75 | 12.63 – 14.87 | <.001 | ||
Carer’s Sex | 0.48 | -0.07 – 1.03 | .087 | 0.67 | 0.10 – 1.25 | .020 | ||
Hours of Care | 0.00 | -0.00 – 0.01 | .233 | 0.00 | -0.00 – 0.01 | .214 | ||
Elder’s Dependency | -0.05 | -0.06 – -0.04 | <.001 | -0.05 | -0.06 – -0.04 | <.001 | ||
Mid Educational Level | 0.19 | -0.43 – 0.80 | .098 | |||||
High Educational Level | 0.80 | 0.03 – 1.58 | .098 | |||||
Random Parts | ||||||||
N_{grp} | 8 | 8 | ||||||
ICC_{grp} | 0.022 | 0.021 | ||||||
Observations | 872 | 815 |
Changing table style
You can change the table style with specific parameters, e.g. to include CI into the same table cell as the estimates, print asterisks instead of numeric p-values etc.
sjt.lmer(fit1, fit2, separateConfColumn = FALSE, # ci in same cell as estimates showStdBeta = TRUE, # also show standardized beta values pvaluesAsNumbers = FALSE) # "*" instead of numeric values
Model 1 | Model 2 | |||||
B (CI) | std. Beta (CI) | B (CI) | std. Beta (CI) | |||
Fixed Parts | ||||||
(Intercept) |
14.14 (13.15 – 15.12) *** |
13.75 (12.63 – 14.87) *** |
||||
sex2 |
0.48 (-0.07 – 1.03) |
0.05 (-0.01 – 0.11) |
0.67 (0.10 – 1.25) * |
0.07 (0.01 – 0.14) |
||
c12hour |
0.00 (-0.00 – 0.01) |
0.04 (-0.03 – 0.12) |
0.00 (-0.00 – 0.01) |
0.05 (-0.03 – 0.12) |
||
barthel |
-0.05 (-0.06 – -0.04) *** |
-0.37 (-0.44 – -0.30) |
-0.05 (-0.06 – -0.04) *** |
-0.37 (-0.44 – -0.30) |
||
education2 |
0.19 (-0.43 – 0.80) |
0.02 (-0.05 – 0.10) |
||||
education3 |
0.80 (0.03 – 1.58) |
0.08 (0.00 – 0.16) |
||||
Random Parts | ||||||
N_{grp} | 8 | 8 | ||||
ICC_{grp} | 0.022 | 0.021 | ||||
Observations | 872 | 815 | ||||
Notes | * p<.05 ** p<.01 *** p<.001 |
Models with different random intercepts
When models have different random intercepts, the sjt.lmer
function tries to detect these information from each model. In the Random parts section of the table, information on multiple grouping levels and ICC’s are printed then.
sjt.lmer(fit1, fit2, fit3)
Model 1 | Model 2 | Model 3 | ||||||||||
B | CI | p | B | CI | p | B | CI | p | ||||
Fixed Parts | ||||||||||||
(Intercept) | 14.14 | 13.15 – 15.12 | <.001 | 13.75 | 12.63 – 14.87 | <.001 | 13.76 | 12.63 – 14.88 | <.001 | |||
sex2 | 0.48 | -0.07 – 1.03 | .087 | 0.67 | 0.10 – 1.25 | .020 | 0.65 | 0.08 – 1.22 | .026 | |||
c12hour | 0.00 | -0.00 – 0.01 | .233 | 0.00 | -0.00 – 0.01 | .214 | 0.00 | -0.00 – 0.01 | .205 | |||
barthel | -0.05 | -0.06 – -0.04 | <.001 | -0.05 | -0.06 – -0.04 | <.001 | -0.05 | -0.06 – -0.04 | <.001 | |||
education2 | 0.19 | -0.43 – 0.80 | .098 | 0.16 | -0.46 – 0.79 | .103 | ||||||
education3 | 0.80 | 0.03 – 1.58 | .098 | 0.79 | 0.01 – 1.57 | .103 | ||||||
Random Parts | ||||||||||||
N_{grp} | 8 | 8 | 8 | |||||||||
N_{carelevel} | 4 | |||||||||||
ICC_{grp} | 0.022 | 0.021 | 0.021 | |||||||||
ICC_{carelevel} | 0.000 | |||||||||||
Observations | 872 | 815 | 807 |
Note that in certain cases, depending on the order of fitted models with several random intercepts, the group label might be incorrect.
Further examples
More details on the sjt.lmer
function can be found in this online-manual.
Tagged: data visualization, mixed effects, multilevel, R, rstats, sjPlot, Statistik, table output
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.