Reputation: 1026
This question comes to mind because I would like to make a slideshow of plots to show a construction that I am trying to make. The plots are all square, and i would like to keep them this way (the axes should have equal scale).
I can do this quite easily, for example:
library(ggplot2)
library(magrittr)
dd <- data.frame(x = runif(100), y = runif(100), z = rexp(100))
dd %>% ggplot(aes(x = x, y = y))
dd %>% ggplot(aes(x = x, y = y)) + geom_point()
You'll notice how the two plots nicely "align", in the sense that if I export them in the same size I can see the points being added in a slideshow-like manner.
However, when a legend appears, the axis get distorted to fit the legend in the same size:
dd %>% ggplot(aes(x = x, y = y)) + geom_point(aes(size = z))
Is there a way to have these 3 plots nicely aligned in a sequence, so that the axes stay in the same place in all 3?
Upvotes: 2
Views: 1171
Reputation: 32789
This will draw the three plots so that the plot panels keep the same shape and size. I use gtable
functions. The first two plots do not have legends. Therefore, I add a column to their gtables so that the layouts for the first two are the same as the layout of the third. Then I make sure the column widths for the first two plots are the same as the widths of the third plot.
If in addition you want the axes to have equal scales, consider adding coord_fixed(ratio = 1)
to each plot.
library(ggplot2)
library(magrittr)
library(gtable)
library(grid)
dd <- data.frame(x = runif(100), y = runif(100), z = rexp(100))
# Get the ggplots
p1 = dd %>% ggplot(aes(x = x, y = y))
p2 = dd %>% ggplot(aes(x = x, y = y)) + geom_point()
p3 = dd %>% ggplot(aes(x = x, y = y)) + geom_point(aes(size = z))
# Get the ggplot grobs
g1 = ggplotGrob(p1)
g2 = ggplotGrob(p2)
g3 = ggplotGrob(p3)
# Add a column to g1 and g2 (any width will do)
g1 = gtable_add_cols(g1, unit(1, "mm"))
g2 = gtable_add_cols(g2, unit(1, "mm"))
# Set g1 and g2 widths to be equal to g3 widths
g1$widths = g3$widths
g2$widths = g3$widths
# Draw them
grid.newpage()
grid.draw(g1)
grid.draw(g2)
grid.draw(g3)
Upvotes: 2
Reputation: 4995
I did not get an 100% exact solution. But I think it is very close. I don't know how to determine the width of the legend labels. If you find out how to do that you could adjust the margins accordingly. For this solution I played arround with the legend and plot margins.
library(dplyr)
library(ggplot2)
dd <- data.frame(x = runif(100), y = runif(100), z = rexp(100))
dd %>% ggplot(aes(x = x, y = y)) +
theme(plot.margin = unit(c(1,3.72,1,1), "cm"))
dd %>% ggplot(aes(x = x, y = y)) + geom_point() +
theme(plot.margin = unit(c(1,3.72,1,1), "cm"))
dd %>% ggplot(aes(x = x, y = y)) + geom_point(aes(size = z)) +
theme(plot.margin = unit(c(1,1,1,1), "cm"),
legend.margin = unit(0.5, "cm"),
legend.text = element_text(size = 12))
Upvotes: 1