1

I think part of this question deals with sjPlot package, but I've found the package to be pretty flexible and to mirror ggplot, so I'm hoping someone has the answer.

If you knit the code I've written below (using mtcars) into a pdf, you'll see that the two plots don't align. Set aside that I've willfully created the situation (making y-axes labels different sizes and non-sensical models), but how could I get the two separate plots to be the same size (despite having different length y-axis labels)? Maybe the best I can do is to z-score them and make sure that none of the y-axis labels exceed a certain length (not ideal, but also not horrible).

In addition, I'm also trying to get it so that there would be no (or minimal) vertical empty space in between the two graphs (so that they nearly overlap). So the first thing would be removing the x-axis labels (estimates) and x-axis title and saving them for the last graph (which I've done), but you can still see that this looks JV. How can I do better?

I have about 10 effect size graphs in two columns (one for Math, one for English, plotting PCA results, etc.), but I think the issue can be distilled to the two graphs you'll get from the Markdown.

Thanks much!

---
title: "Untitled"
author: "Effect Sizes"
date: "1/25/2020"
output:
  pdf_document: default

---
```{r echo = FALSE, include=FALSE}

library(tidyverse)
library(lme4)
library(sjPlot)
library(sjlabelled)
```

```{r effect size dem, echo=FALSE, warning=FALSE, message=FALSE, fig.height = 1.1, fig.width = 4, fig.show="hold", fig.align="center"}

mpg <- lmer(mpg~wt + gear + carb + (1|cyl), mtcars, na.action = 'na.exclude', control = lmerControl(optimizer = "nloptwrap", calc.derivs = FALSE), REML = FALSE)

hp <- lmer(mpg~hp + (1|cyl), mtcars, na.action = 'na.exclude', control = lmerControl(optimizer = "nloptwrap", calc.derivs = FALSE), REML = FALSE)

plot_model(mpg, type = "std", title = "")+
  theme(axis.text.x = element_blank(),
         axis.title.x = element_blank())+
  xlab("")+
  ylim(-1,1)


labels <- c(hp = "horse power")
plot_model(hp, type = "std", title = "", axis.labels = labels)+
  xlab("")+
  ylim(-1,1)

```
tjebo
  • 21,977
  • 7
  • 58
  • 94
James
  • 459
  • 2
  • 14

2 Answers2

1

There might be several ways. This is my solution using ggpubr. I changed the last chunk:


mpg <- lmer(mpg~wt + gear + carb + (1|cyl), mtcars, na.action = 'na.exclude', control = lmerControl(optimizer = "nloptwrap", calc.derivs = FALSE), REML = FALSE)

hp <- lmer(mpg~hp + (1|cyl), mtcars, na.action = 'na.exclude', control = lmerControl(optimizer = "nloptwrap", calc.derivs = FALSE), REML = FALSE)

a <- plot_model(mpg, type = "std", title = "")+
  theme(axis.text.x = element_blank(),
         axis.title.x = element_blank())+
  xlab("")+
  ylim(-1,1)

labels <- c(hp = "horse power")

b <- plot_model(hp, type = "std", title = "", axis.labels = labels)+
  xlab("")+
  ylim(-1,1)
library(ggpubr)
ggarrange(a, b, ncol = 1, nrow = 2, 
          align = "v")

to get something like:

enter image description here

Zhiqiang Wang
  • 6,206
  • 2
  • 13
  • 27
  • This also works very nice. I see that it's aligned vertically. If I had two separate columns, one for math and one for English and wanted these plotted side by side, how would I alter the code? I tried, show = "h" but no dice. Also, if the first graph has many more coefficients, is there anyway to size the graphs proportionally? I'll look into the ggpubr package as well. Thanks. – James Feb 12 '20 at 21:56
1

I'd not rely on markdown knitting in this case. Align the plots with a package, e.g. patchwork is great.

You need to adjust the plots margins in order to make the distance between the plots smaller. However, I feel that trying to make the vertical distance disappear between each plot would visually suggest that the same model was used for all predictions, which is not the case - thus this would be misleading.

p1 <- 
  plot_model(mpg, type = "std", title = "")+
  theme(axis.text.x = element_blank(),
        axis.title.x = element_blank(),
        axis.ticks.x = element_blank(),
        plot.margin = margin(b = 0))+
  labs(x = NULL) +
  ylim(-1,1)

labels <- c(hp = "horse power")

p2 <- 
  plot_model(hp, type = "std", title = "", axis.labels = labels)+
  labs(x = NULL) +
  theme(plot.margin = margin(b = 0)) +
  ylim(-1,1)

library(patchwork)

p1 /  p2 

the image shows a screenshot from the RStudio preview of an rmarkdown notebook enter image description here

tjebo
  • 21,977
  • 7
  • 58
  • 94
  • First, this is AM-MAZ-ING. Exactly what I was looking for and a HUGE help. Second, let's say I had twenty variables in the first graph and only five in the second. The first graph looks incredibly cramped...and there would be too much space in the second graph (think of your example but exaggerated). What could I do about that? I tried messing with the ylim() but it doesn't have an effect. How else can I adjust figure height without using rmarkdown and having the different size graphs in different chunks? – James Feb 12 '20 at 21:12
  • Also, you're right about not making the vertical distance disappear. Your example is perfect. – James Feb 12 '20 at 21:17
  • @JimmyAdes glad it helped. Have a look at https://cran.r-project.org/web/packages/patchwork/patchwork.pdf in particular `plot_layout`. This allows you to change plot dimensions. Patchwork is an amazing package and I use it a lot. Also, if there is too much empty space, you could use the `expand` argument in `scale_x`, but I am not sure if this will work with sjplot wrapper – tjebo Feb 12 '20 at 22:19