Combine ggplots but fix the size/ratio of the plots
Asked Answered
L

2

3

I have two plots that I combine. arrangeGrob() squeezes them so that the size of the new image is the same as one alone. How can I arrange them while preserving the ratio/size?

require(ggplot2)
require(gridExtra)

dat <- read.csv("http://www.ats.ucla.edu/stat/data/fish.csv")

frqncy <- as.data.table(table(dat$child))#
frqncy$V1 <- as.numeric(frqncy$V1)

plot1 <- ggplot(frqncy, aes(x=V1, y= N)) +
    geom_histogram(stat="identity", binwidth = 2.5)
plot2 <- ggplot(frqncy, aes(x=V1, y= N)) +
    geom_density(stat="identity")

plot <- arrangeGrob(plot1, plot2)

Plot looks like

Plots become smaller when combined

I have not found any parameter in ggplot() or arrangeGrob() that fixes the ratio of the input.

Edit: Additional complications arise from the definition of axis labels in arrangeGrob(), i.e.

plot <- arrangeGrob(plot1, plot2, left="LHS label")

Then the new file will not automaticall shrink to the minimum height/width combination of plot1 and plot2.

Locative answered 28/9, 2014 at 19:30 Comment(0)
D
3

You can control this when you output to a device. For example, a PDF file:

pdf("plot.pdf", width=5,height=8)
plot
dev.off()

enter image description here

Another option is to set a fixed ratio between the x and y coordinates in the plot itself using coord_fixed(ratio=n), where n is the y/x ratio. This will set the relative physical length of the x and y axes based on the nominal value range for each axis. If you use coord_fixed() the graph will always maintain the desired aspect ratio no matter what device size you use for your output.

For example, in your case both graphs have x-range 0 to 3 and y-range 0 to 132. If you set coord_fixed(ratio=1), your graphs will be tall and super skinny because the x-axis length will be 3/132 times the y-axis length (or to put it another way, 1 x-unit will take up the same physical length and 1 y-unit, but there are only 3 x-units and 132 y-units). Play around with the value of ratio to see how it works. A ratio of somewhere around 0.02 is probably about right for your graphs.

As an example, try the following code. Here I've set the ratio to 0.1, so now 1 x-unit takes up 10 times the physical length of each y-unit (that is, 0 to 3 on the x-axis has the same physical length as 0 to 30 on the y-axis).

plot1 <-ggplot(frqncy, aes(x=V1, y= N)) +
  geom_histogram(stat="identity", binwidth = 2.5) + 
  coord_fixed(ratio=0.1)
plot2 <- ggplot(frqncy, aes(x=V1, y= N)) +
  geom_density(stat="identity") +
  coord_fixed(ratio=0.1)

plot <- arrangeGrob(plot1, plot2)

pdf("plot.pdf", 5,8)
plot
dev.off()

enter image description here

Dulla answered 28/9, 2014 at 20:27 Comment(0)
C
9

there are several other options, depending on what you want*

library(ggplot2)
p = qplot(1, 1)
grid.arrange(p, p, respect=TRUE) # both viewports are square
grid.arrange(p, p, respect=TRUE, heights=c(1,2)) # relative heights

p1 = p + theme(aspect.ratio=3)
grid.arrange(p,p1, respect=TRUE) # one is square, the other thinner

*: the aspect ratio is often not a well-defined property of plots (unless set manually), because the default is to extend the plot to the available space defined by the plot window/device/viewport.

Charters answered 28/9, 2014 at 22:5 Comment(5)
respect=TRUE, that's all I needed. I wonder why it's not in the documentary.Locative
package author's laziness, if you ask meCharters
I have to admit I was to early in my enthusiasm. Plot (in your case p) is quadratic although the two plots in it are also quadratic. This means that the plots are much smaller while most of the file plot/p is white border. Resizing in the final document is useless.Locative
i don't really get it. Do you have a minimal reproducible example to illustrate your problem (edit your question)?Charters
Yes, I meant square. Sorry for the confusion. I think the problem comes from the fact that I add my axis labels in the arrangeGrob() environment (which wasn't part of the first version of the question).Locative
D
3

You can control this when you output to a device. For example, a PDF file:

pdf("plot.pdf", width=5,height=8)
plot
dev.off()

enter image description here

Another option is to set a fixed ratio between the x and y coordinates in the plot itself using coord_fixed(ratio=n), where n is the y/x ratio. This will set the relative physical length of the x and y axes based on the nominal value range for each axis. If you use coord_fixed() the graph will always maintain the desired aspect ratio no matter what device size you use for your output.

For example, in your case both graphs have x-range 0 to 3 and y-range 0 to 132. If you set coord_fixed(ratio=1), your graphs will be tall and super skinny because the x-axis length will be 3/132 times the y-axis length (or to put it another way, 1 x-unit will take up the same physical length and 1 y-unit, but there are only 3 x-units and 132 y-units). Play around with the value of ratio to see how it works. A ratio of somewhere around 0.02 is probably about right for your graphs.

As an example, try the following code. Here I've set the ratio to 0.1, so now 1 x-unit takes up 10 times the physical length of each y-unit (that is, 0 to 3 on the x-axis has the same physical length as 0 to 30 on the y-axis).

plot1 <-ggplot(frqncy, aes(x=V1, y= N)) +
  geom_histogram(stat="identity", binwidth = 2.5) + 
  coord_fixed(ratio=0.1)
plot2 <- ggplot(frqncy, aes(x=V1, y= N)) +
  geom_density(stat="identity") +
  coord_fixed(ratio=0.1)

plot <- arrangeGrob(plot1, plot2)

pdf("plot.pdf", 5,8)
plot
dev.off()

enter image description here

Dulla answered 28/9, 2014 at 20:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.