3

This question in regarding formatting plots produced using ggplot2 + ggExtra and is not related to any bug.

require(ggplot2)
#> Loading required package: ggplot2
require(ggExtra)
#> Loading required package: ggExtra
p1 <- ggplot(data = mpg,aes(x = cty,y = cty)) + 
  geom_point()+ 
  xlab("City driving (miles/gallon)") +
  ylab("City driving (miles/gallon)")

ggMarginal(p = p1,type= "boxplot")

The y-axis marginal plot in this chart is usually not similar to the x-axis marginal plot i.e. the width of the 2 boxplots are not similar. This problem become more acute when I change plot dimensions (in my case, using RStudio). Any suggestions how to make the width of the 2 boxplots similar while using different plot dimensions (width x height).

I face similar problems with other marginal plot type options provided by ggExtra package: histogram, density.

Vikrant
  • 125
  • 8
  • Try adding `coord_fixed()` to the original plot? `ggMarginal()` has a size parameter (defaulting to 5), which describes the **relative** marginal plot size compared to the main plot. This parameter applies to both x & y axis. – Z.Lin Nov 23 '17 at 05:19

2 Answers2

6

I suggest the axis_canvas function from the cowplot package. (Disclaimer: I'm the package author.) It requires a little more work, but it allows you to draw any marginals you want. And you can specify the size exactly, in output units (e.g. inch).

require(cowplot)

pmain <- ggplot(data = mpg, aes(x = cty, y = hwy)) + 
  geom_point() + 
  xlab("City driving (miles/gallon)") +
  ylab("Highway driving (miles/gallon)")

xbox <- axis_canvas(pmain, axis = "x", coord_flip = TRUE) + 
  geom_boxplot(data = mpg, aes(y = cty, x = 1)) + coord_flip()
ybox <- axis_canvas(pmain, axis = "y") + 
  geom_boxplot(data = mpg, aes(y = hwy, x = 1))

p1 <- insert_xaxis_grob(pmain, xbox, grid::unit(1, "in"), position = "top")
p2 <- insert_yaxis_grob(p1, ybox, grid::unit(1, "in"), position = "right")
ggdraw(p2)

See how the boxplots retain their width/height in the following two images with different aspect ratios. (Unfortunately Stackoverflow rescales the images, so the effect is somewhat obscured, but you can see that the height of the top boxplot is always equal to the width of the side one.)

enter image description here

enter image description here

The second advantage is that because you can use full-blown ggplot2 for your marginal plots, you can draw anything you want, e.g. grouped box plots.

require(cowplot)

pmain <- ggplot(data = mpg, aes(x = cty, y = hwy, color = factor(cyl))) + 
  geom_point() + 
  xlab("City driving (miles/gallon)") +
  ylab("Highway driving (miles/gallon)") +
  theme_minimal()

xbox <- axis_canvas(pmain, axis = "x", coord_flip = TRUE) + 
  geom_boxplot(data = mpg, aes(y = cty, x = factor(cyl), color = factor(cyl))) + 
  scale_x_discrete() + coord_flip()
ybox <- axis_canvas(pmain, axis = "y") + 
  geom_boxplot(data = mpg, aes(y = hwy, x = factor(cyl), color = factor(cyl))) +
  scale_x_discrete()

p1 <- insert_xaxis_grob(pmain, xbox, grid::unit(1, "in"), position = "top")
p2 <- insert_yaxis_grob(p1, ybox, grid::unit(1, "in"), position = "right")
ggdraw(p2)

enter image description here

Claus Wilke
  • 16,992
  • 7
  • 53
  • 104
  • Nice solution @ClausWilke. But perhaps a full disclaimer would've been in order, clarifying that you're the `cowplot` dev. – Maurits Evers Nov 23 '17 at 09:09
  • Agree on the disclaimer bit. But super solution @ClausWilke- thanks a lot! – Vikrant Nov 23 '17 at 09:48
  • Disclaimer added. – Claus Wilke Nov 23 '17 at 17:15
  • @ClausWilke (Although your code solves the main problem, wanted clarification on one more related aspect): Is there anyway we can create a slight gap/ spacing between the main plot & the marginal plots? – Vikrant Nov 28 '17 at 13:51
  • There are at least two approaches (probably others exist also): (i) when drawing the marginal plots, chose the limits of the orthogonal axes so there is some space; (ii) call `insert_x/yaxis_grob` twice and insert an empty grob after inserting the marginal plot. This is really a separate question. Why don't you post it as such and ping me here. – Claus Wilke Nov 28 '17 at 14:04
  • @Vikrant I have now addressed your question about gaps [here.](https://stackoverflow.com/q/47542849/4975218) – Claus Wilke Nov 28 '17 at 23:49
  • @ClausWilke: Very Odd! Since I can’t comment on your new post I am asking my question here: Hi, Thanks as always for the precise solution. In solution #2 (Create gap in the marginal plots): how did you decide the limits? Also, what’ll happen if we used “NA” as the upper limit? – Vikrant Nov 29 '17 at 01:59
  • @Vikrant: Why don't you ask this as a stand-alone question? I should have let you ask the other question in the first place. You need to keep asking questions to gain reputation so you can comment, and your questions are good. The answer to this question is easy, so others will likely discover it if I don't immediately see your question. – Claus Wilke Nov 29 '17 at 02:51
  • @ClausWilke: Will do so. – Vikrant Nov 29 '17 at 05:06
  • This is a nice solution applicable for a wider range of margin plots, yet it is easy to make mistakes as there is no scale to check the margin plots. Note that xlim/ylim do not get carried over to `axis_canvas()` from pmain. You'll need to add the same limits than you use in pmain. You may override the defaults by adding theme_bw() to the axis_canvas to check that the coordinate systems are equal. – Mikko May 06 '22 at 12:21
1

I'm not entirely sure what you mean. Setting width=height of your output plot ensures the same width of the boxplots.

For example, in RMarkdown, if I include

```{r, fig.width = 5, fig.height = 5}
ggMarginal(p1, type = "boxplot", size = 2);
```

I get the following output

enter image description here

The box widths are identical.

Alternatively, if you save your plot make sure to set the same width and height.

ggsave(file = "test.png", ggMarginal(p1, type = "boxplot", size = 2), width = 5, height = 5);
Maurits Evers
  • 49,617
  • 4
  • 47
  • 68
  • Hi, Thanks a lot for your suggestion. Can I create a plot with different width/ height (e.g. width=10, height=5) and still get marginal boxplots with similar width (of box that includes the 1,2,3rd quartile)? – Vikrant Nov 23 '17 at 05:57
  • 1
    @Vikrant No, you can't with ggMarginal. It sets the sizes of the marginal plots relative to the height/width of the main plot, and therefore an aspect ratio that is not 1:1 translates into distorted marginal plots. The solution is to use absolute rather than relative sizing, but I don't think ggMarginal currently supports that, at least not according to the documentation. – Claus Wilke Nov 23 '17 at 07:22