Keeping proportions when exporting ggplots

57 views Asked by At

I am having trouble exporting ggplot figures and keeping the right dimensions. Single elements always appear bloated and the physical dimensions do not match the provided definitions or grow even larger. The problem is best explained in the examples below, which already include suggestions I found after lots of searching.

library(ggplot2)
# example data
y <- rnorm(5, mean = 3)
barfill <- c("Elefants", "Shoes", "Soup", "Elefants", "Soup")
# plot
p <- ggplot() + 
  geom_col(aes(x = 1:5, y = y, fill = barfill)) + 
  geom_text(aes(x = 1:5, y = y-0.5, label = c("there", "are", "five", "columns", "here"))) +
  labs(title = "A random figure", subtitle = "with a couple of elements")


# scaling solutions for exporting the plot

# 1 - standard export  # appears crowded
ggsave(filename = "testbars.jpg", plot = p, width = 75, height = 75, units = "mm", dpi = 300)

# 2 - adjusting text size  # still out of proportions
p2 <- p + theme(text = element_text(size = 6))   # does not scale geom_text
### p2 +  update_geom_defaults("text", list(size = 4))  # this would scale geom_text, but changes defaults and thereby messes up other figures
ggsave(filename = "testbars_textscaled.jpg", plot = p2, width = 75, height = 75, units = "mm", dpi = 300)  

# 3 - scale entire image  # looks good, but image dimensions grow
ggsave(filename = "testbars_scaled.jpg", plot = p, width = 75, height = 75, units = "mm", dpi = 300, scale = 2.2)  

The first image looks as if Picasso would write a publication, while the second is already slightly better, although geom_text is not scaled and neither are other elements, such as the legend-boxes. Using update_geom_defaults("text", list(size = 5)) solves the geom_text issue, but at the cost that other plots get affected by the altered overall defaults (which is not an option for me). The third solution (testbars_scaled.jpg) using the scale function of ggsave provides a figure as I would be aiming for. However, the function drastically expands the physical dimensions, probably by increasing the distances between the single elements. Manually shrinking the figures to the desired size when later inserting into the text does not appear like the proper way to go. Image dimensions is also an issue in the previous approaches, the physical dimensions always turn out bigger than defined in ggsave, even though dimensions and units are properly provided (?).

Is there a way to achieve the effect of the third approach, while getting an image with dimensions as specified, or another way to otherwise export figures with proper proportions? As hundreds of standardised figures will have to be created, the solution should ideally not involve manually adjusting the image dimensions with the cursor, but be suitable for automatisation.

Thanks and Greetings!

1

There are 1 answers

0
anothernoob On

Thank you all for your helpful answers!

Here is what so far provides me the best results: The helpful link posted in the first comment refers to another useful article: https://www.tidyverse.org/blog/2020/08/taking-control-of-plot-scaling/

Apparently, someone faced the same issue and implemented a scaling solution to the ragg library, which seems to scale really everything without increasing image dimensions.

library(ragg)
agg_jpeg(filename = "ragg.jpg", width = 75, height = 75, units = "mm", res = 300, scaling = 0.5)
plot(p)
invisible(dev.off())

The generated figure has the same dimensions as an unscaled plot, but its elements are sized in and with proper proportions. The linked article also mentions, that this solution could also be accessed via ggsave by changing the device: ggsave(device = agg_jpeg, [...]) This (at least for me) however resorts back to the initial ggsave scaling with increase image size. Fortunately the agg_jpeg approach so far seems to solve the issue for me.