How To Set Plot Size In R
Some fourth dimension ago, while working on the new edition of the ggplot2 book, I asked out to the R twitterverse what part of using ggplot2 was the most incomprehensible for seasoned users. By a very large margin the near "popular" response revolved around making sure that output had the correct scaling of text, lines, etc.
The latest release of ragg contains a new functionality that will hopefully make this issue a affair of the past. Read on how to use information technology.
Some definitions
Before we delve into the problem nosotros should analyze a few concepts related to graphics and sizing:
Accented size: This is the physical dimensions of the graphic (or, more precisely, the intended physical dimensions). This is measured in centimeters or inches or some other absolute length unit.
Pixel size: For raster output, the graphic is encoded as a matrix of color values. Each cell in the matrix is a pixel. The pixel size is the number of rows and columns in the matrix. Pixels does non accept any inherent concrete size.
Resolution: This number ties absolute and pixel size together. It is ordinarily given in ppi (pixels per inch), though dpi (dots per inch) is used interchangeably. A resolution of 72 ppi means that an inch is considered 72 pixels long.
Pointsize: This is a measure out tied to text sizing. When we set up a font to size 12, information technology is given in points. While the actual size of a point has varied throughout history, the general consensus now is that 1pt = one/72 inch (this is too adopted by R). Since points is an accented unit, the resolution of the output will determine the number of pixels it correspond to.
The problem
With formalities out of the manner, nosotros tin describe the problem more clearly. At its core, this is about ensuring the right scaling of a plot as nosotros develop it for varying absolute sizes.
When nosotros develop a graphic we will generally sit in front of a estimator and fine melody information technology while continuously getting previews on the screen. Once we are content with it we will save it to the correct absolute size required past wherever we intend to publish the plot. In the remainder of the text nosotros will assume that we sit down in front end of a reckoner developing a plot that should stop up on a poster.
This is the plot, and how it looks on a estimator:
library(ggplot2) library(ragg) library(palmerpenguins) # plot adapted from https://github.com/allisonhorst/palmerpenguins p <- ggplot(na.omit(penguins), aes(10 = flipper_length_mm, y = body_mass_g)) + geom_point( aes(color = species, shape = species), size = iii, alpha = 0.8 ) + ggforce::geom_mark_ellipse( aes(filter = species == "Gentoo", description = "Gentoo penguins are mostly bigger in size") ) + labs(x = "Flipper Length [mm]", y = "Trunk Mass [g]", colour = "Species", shape = "Species") pngfile <- fs::path(knitr::fig_path(), "basis.png") # I'm explicitly calling the device functions then yous tin can see the dimensions # used agg_png(pngfile, width = 20, peak = 12, units = "cm", res = 300) plot(p) invisible(dev.off()) knitr::include_graphics(pngfile)
This looks good, but remember nosotros want to use this on a poster. A affiche is ordinarily observed at a farther altitude than a computer screen, so in guild to make information technology legible the plot should exist bigger. How much bigger? Well, if we presume that we are watching our screen at 50 cm distance, and our poster is meant to be observed at 1.five m distance, then our plot should be three times larger to take upwardly the same corporeality of space in our vision:
With that in mind nosotros rapidly size upwards our plot:
The plot above doesn't expect physically larger, but that is considering the webpage downscales it to make information technology fit. You tin download each of the images and open them in a epitome editor to convince yourself that they are of different accented size. The downscaling done by the webpage allows u.s. to simulate how looking at our affiche may feel similar, and it is not pretty; everything seems super small and ineligible.
Why is that? Our plot is a mix of elements positioned and dimensioned based on both relative and absolute sizes. While the relative sizes expand along with the output size, the absolute sizes does not. The text is given in points which, equally you recollect, is an absolute dimension. The aforementioned is true for the element sizes in the scatterplot, the grid lines, etc. This ways that as nosotros scale up the output size, they remain the same size and will thus get smaller relative to the full paradigm.
The reverse can be a trouble as well. If y'all return a plot to a smaller size than the i you've previewed you may observe that text, margins, etc. take upward all the available space.
Now, how should we go about correcting this?
Try 1: Use vector graphics
The discussion to a higher place is especially relevant to raster output since they don't resize gracefully and it is thus very important to get the correct dimensions and resolution when information technology is rendered. I way to resolve this is to non render to raster simply use a vector graphic device such as pdf() or svglite(). With these you tin simply render the graphic to a size where everything looks every bit it should and and so resize the output to the concrete size that you need. There are valid reasons to not desire to utilise vector graphics, even so. The wait of the output may alter depending on which programme opens them. Custom fonts may not return correctly on other systems. Or you may take such a large amount of graphical elements that the vector graphic becomes unreasonably big and heavy to display. If none of this applies then using a vector graphic device is definitely a valid and reasonable solution. For the remainder of the post nosotros assume that we want the output in a raster format such as png and explore how we may set our scaling issues there.
Endeavour 2: Theming
One approach to fixing this is by changing the theme settings of the plot, so that they work better for a larger size:
This approach got u.s. surprisingly far. A lot of the theme elements of the plot is derived from the base size argument so many adapts. Not all though, as we can run into the legend keys maintaining their relative small-scale size. If yous've been using a custom theme it may as well be that y'all've overwritten some of the default sizes and will need to change that as well.
One affair missing is all the non-theme elements (i.e. things part of the layer). Because of this nosotros'd have to redo the whole plot in society to get the desired result:
p1 <- ggplot(na.omit(penguins), aes(x = flipper_length_mm, y = body_mass_g)) + geom_point( aes(color = species, shape = species), size = 9, alpha = 0.eight ) + ggforce::geom_mark_ellipse( aes(filter = species == "Gentoo", clarification = "Gentoo penguins are mostly bigger in size"), size = 1.5, label.fontsize = 36 ) + labs(x = "Flipper Length [mm]", y = "Body Mass [grand]", colour = "Species", shape = "Species") + theme_gray(base_size = 33) pngfile <- fs::path(knitr::fig_path(), "theming2.png") agg_png(pngfile, width = 60, superlative = 36, units = "cm", res = 300) plot(p1) invisible(dev.off()) knitr::include_graphics(pngfile)
We tin can see that we are getting in that location, but the journey hasn't been pleasant. Especially for the last part it requires noesis of all the different settings in a geom that encodes absolute sizes. For the marking geom we only fixed the ellipse line width and the text size, but in that location are many more settings that needs to exist updated besides every bit is credible from the weird look of the text box.
Another issue that arises is that if nosotros need this plot at yet another different scale, we will need to change quite a lot of code in order to become at that place.
Try 3: Resolution scaling
Since the resolution is the parameter that ties the pixel size and absolute size together it is possible to utilize it every bit a scaling factor, merely it requires some non-obvious adjustments:
The start affair we demand to practise is convert our physical dimensions to pixel dimensions using our desired resolution. We want to end upwardly with a 60x36cm plot at 300ppi. This gives us:
c(60, 36) * 0.3937 * # convert to inch 300 # convert to pixels #> [1] 7086.60 4251.96 We can at present use these values straight in our device and change the resolution of the device to pull a fast one on it into thinking that text etc should be rendered at a larger size
This actually works exactly every bit nosotros hoped. Nosotros've gotten our huge version of the plot only with the same exact scaling of all graphic elements.
Depending on your temperament this may be a perfect solution. To me, I think the conversion from physical dimensions to pixels is boring, and it has the added drawback that the dimensions of the plot is incorrectly encoded (it will appear every bit a 20*12cm plot at 900ppi) which may affect how information technology is presented in different programs. In the stop you may take to manually resize it to go the correct physical dimensions in the end.
The solution
Seeing that at that place is no single perfect solution to fixing this with the tools at our disposal, I've added a new argument to the ragg devices called scaling. It'southward a multiplier that is applied to all absolute sizes, without interfering with the encoded dimensions of the output. Since nosotros have increased the dimensions iii times we set up scaling = three to make sure that the absolute sized elements are keeping their relative size.
Every bit can exist seen, the new argument makes it very easy to repossess the look of the plot later resizing. Hopefully this volition remove a good deal of the pain related to generating plots for papers, posters, presentations, etc. Yous practise have to call back to use the same scaling setting for all plots for them to accept the same sizing, but apart from that it makes it very easy to fine tune the wait for the medium your creating it for.
Remember that the scaling cistron of 3 was only called to fit our presumed viewing distance and should non be repeated without idea. Some other example would be to create a small version of the plot, eastward.g. for a thumbnail on a webpage. While in that location is no harm in manually scaling downward a raster prototype, you may find that specially text is more than readable when rendered to the desired size directly. To show this off we'll make a half-sized version of our plot equally well. To spruce information technology up nosotros'll use ggsave() instead of calling the ragg device directly. Allow's encounter how it looks without using scaling first:
Every bit nosotros tin can see, everything feels oversized for the plot, and the margins takes upwardly fashion too much relative space. Using scaling we rapidly resolve this:
pngfile <- fs::path(knitr::fig_path(), "downscaling.png") ggsave( pngfile, p, device = agg_png, width = 10, pinnacle = 6, units = "cm", res = 300, scaling = 0.v ) knitr::include_graphics(pngfile)
Addendum
- Preparing graphics for the web presents an additional hurdle. The HTML specification assumes a screen resolution of 96ppi since that was the predominant screen resolution at the time. Modern monitors have a much higher resolution only the assumption is still in effect (though operating systems may mitigate information technology). This is the reason why plots may await slightly smaller when rendered through Shiny, blogdown, or hugodown. But set up the resolution to 96ppi and use pixel dimensions for the output to make certain it has the correct scaling.
- Rendering images with RMarkdown requires some care as well since chunk options both take an output dimension in inches as well as a scaling gene for how big the rendered epitome should appear in the certificate. R for Data Science has some additional data on this
How To Set Plot Size In R,
Source: https://www.tidyverse.org/blog/2020/08/taking-control-of-plot-scaling/
Posted by: diazmays1961.blogspot.com

0 Response to "How To Set Plot Size In R"
Post a Comment