Beautiful table-outputs: Summarizing mixed effects models #rstats

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
Ngrp 8 8
ICCgrp 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
Ngrp 8 8
ICCgrp 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
Ngrp 8 8
ICCgrp 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
Ngrp 8 8
ICCgrp 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
Ngrp 8 8 8
Ncarelevel 4
ICCgrp 0.022 0.021 0.021
ICCcarelevel 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.

23 Kommentare zu „Beautiful table-outputs: Summarizing mixed effects models #rstats

  1. Hello Daniel

    NIce work. I would like to explore if can generate Latex output so that it can be integrated with traditional report writing paradigm.

    1. Latex is currently not supported, however, you can use the tables inside knitr-documents, see here. As I’m not that familiar with Latex, I’m not sure, whether I’ll add Latex support to my package. Last thing I remember is that tables in Latex are a pain 😉

  2. Hi, excellent work, CONGRATS!!! Is this new version compatible to R version 3.2.0? Is there any binary for Mac OS?? I have been using the earlier version 1.8 and the function sjt.lmer is not there. Thanks

    1. sjPlot 1.8.1 is available on CRAN, simply updating your packages should install the latest version. sjPlot >= 1.8 depends on R >= 3.1, hence the package should work on all R-Version from 3.1 to current.

  3. Hi Daniel, I have tried to install the OS X Mavericks binaries of sjPlot 1.8.1 and got the warning message below after I have run the command „install.packages(„~/Downloads/sjPlot_1.8.1.tar“)“ on Rstudio.

    „Warning in install.packages :
    package ‘~/Downloads/sjPlot_1.8.1.tar’ is not available (for R version 3.2.0)“

    and the package didn’t install at all.
    Thanks
    A.

  4. Seems like a well thought out package that may fill a niche for glmms. I’m using the sjt.glmer function, and I’m wondering where the CI and p-values come from. Could you explain what method was used to calculate them? Is there a way to exclude p-values entirely from the table output, and is it possible to display AICc instead of AIC? Many thanks

    1. CI-values are returned by lme4::confint.merMod(fit, method = "Wald")))). p-values are included in summary(fit) (for generalized mixed models). For lmer, p-values are returned when using the lmerTest-package, else approximate p-values are obtained via car::Anova(fit, type = "III").

      Currently, there’s no option to exclude p-values, however, I can add that option to the table outputs of (g)lmer-summaries. According to AICc: I haven’t heard of this coefficient before, but I’ll see if and how I can include it as well.

      1. Thank you for the information! I do like to know what’s going on behind the scenes, and not everyone uses P-values with models, and be able to exclude significance using P-values will make you’re package more universal. AICc is AIC corrected for small sample sizes, and I know AICc can be accessed by MuMin::model.sel(fit). If you can pull out the information, I don’t know.

        Keep up the good work!

      2. Hi,

        I actually have a question about the confidence intervals. Here you state that they are Wald CI’s but when I use the function it states it is computing profile confidence intervals, which sucks because I have complex models that take forever to compute (as do their profile confidence intervals). Is there any way to change the internal function to make sure it computes the Wald CI’s instead, they’re much quicker to compute.

      3. Actually, sorry, I figured it out. I was using sjt.lmer on glmer models (I didn’t realize there was a different function for logistic models). Thank you for such an awesome package!

  5. Hi! Wow, this really is impressive, are you considering adding the random intercept and slopes as well to the table? Or is that an option, that I’ve missed?

  6. Dear Daniel,
    when running the sjt.lmer command to my linear mixed-effects model I get the following error:
    „Error in eval(expr, envir, enclos) : object ‚Leaves‘ not found“
    Where Leaves is the response variable. I think that this is because in the model I use log(Leaves+1) instead of Leaves itself, in order to get only positive values.
    Do you know whether there is a way to solve this issue?

    Thanks,
    Luisa

  7. Dear Daniel, I would like to include the random effects in my table. Is there a possibility for this?
    Thank you, Anne

  8. Hi Daniel, the function sjt.lmer prints also a r^2 value for each model. How do you calculate the value? Thanks for contributing your great package! Christian

  9. Great. Thanks for the lightning-fast answer. Your package is very useful!

  10. Hi Daniel, i am a bit confused and lost with ICC value in the output from sjt.lmer. Here (https://rdrr.io/cran/sjstats/man/icc.html) i have found a CAUTION paragraph in the man:

    Caution: For models with random slopes and random intercepts, the ICC would differ at each unit of the predictors. Hence, the ICC for these kind of models cannot be understood simply as proportion of variance (see Goldstein et al. 2010). For convenience reasons, as the icc() function also extracts the different random effects variances, the ICC for random-slope-intercept-models is reported nonetheless, but it is usually no meaningful summary of the proportion of variances.

    This CAUTION paragraph do not appear in the current R Doc for icc{stat}. In my case i have run two models with correlated random intercept and slope x + (x | g) and a second model (add group) x * x1 + (x | g). Same procedure as Bates (2010) did by example on sleepstudy data (first model).

    can i interpret the ICC for both models? Should i report ICC for both models?

    Cheers Christian

    1. Hi Christian, the new documentation for „icc()“ is correct, i.e. take care of what is written in the CAUTION paragraph. In short, ICC for random-slope-intercept-models is almost meaningless, unless you (manually) compute the ICC for specific levels of your random slope predictor.

Kommentare sind geschlossen.