ggplot2, ggsave dpi and figure size woes

I am having trouble with saving publication-ready plots in ggplot2, or perhaps just don't understand how ggplot2/ggsave works. The following code saves a plot on my computer that is roughly 20"x20" with 72 dpi. I need to plot to be roughly 5"x5" with > 300 dpi.

Thank you!

library(tidyverse)

df <- tibble(
a = rnorm(100, 5, 1),
b = a + rnorm(100, 0, .5)
)

df %>% 
  ggplot(aes(a, b)) +
  geom_point()

ggsave('plot.png', dpi = 300, height = 5, width = 5, unit = 'in')

sessionInfo()

# R version 4.0.3 (2020-10-10)
# Platform: x86_64-apple-darwin17.0 (64-bit)
# Running under: macOS Catalina 10.15.7
#

 
# Matrix products: default
# BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
# LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib
# 
# locale:
# [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
# 
# attached base packages:
# [1] stats     graphics  grDevices utils     datasets  methods   base     
# 
# other attached packages:
# [1] here_1.0.1         ggpmisc_0.3.8-1    RColorBrewer_1.1-2 GGally_2.1.0       forcats_0.5.1      stringr_1.4.0     
# [7] dplyr_1.0.5        purrr_0.3.4        readr_1.4.0        tidyr_1.1.2        tibble_3.1.0       ggplot2_3.3.3     
# [13] tidyverse_1.3.0   
# 
# loaded via a namespace (and not attached):
# [1] progress_1.2.2    tidyselect_1.1.0  haven_2.3.1       colorspace_2.0-0  vctrs_0.3.6       generics_0.1.0   
# [7] yaml_2.2.1        utf8_1.1.4        rlang_0.4.10      pillar_1.5.1      glue_1.4.2        withr_2.4.1      
# [13] DBI_1.1.1         dbplyr_2.1.0      modelr_0.1.8      readxl_1.3.1      lifecycle_1.0.0   plyr_1.8.6       
# [19] munsell_0.5.0     gtable_0.3.0      cellranger_1.1.0  rvest_1.0.0       labeling_0.4.2    fansi_0.4.2      
# [25] broom_0.7.4       Rcpp_1.0.6        scales_1.1.1      backports_1.2.1   jsonlite_1.7.2    farver_2.1.0     
# [31] fs_1.5.0          digest_0.6.27     hms_1.0.0         stringi_1.5.3     grid_4.0.3        rprojroot_2.0.2  
# [37] cli_2.3.1         tools_4.0.3       magrittr_2.0.1    crayon_1.4.1      pkgconfig_2.0.3   ellipsis_0.3.1   
# [43] prettyunits_1.1.1 xml2_1.3.2        reprex_1.0.0      lubridate_1.7.9.2 assertthat_0.2.1  reshape_0.8.8    
# [49] httr_1.4.2        rstudioapi_0.13   R6_2.5.0          compiler_4.0.3

you have made a 1500 by 1500 image. if there should be a dpi of 300 this would be 5inch dimensions. I don't know what application you are using to show you image dimensions...
what happens when you change 72 to 300 ?

The image is opened in preview (mac's default viewer). I'm using the 'show inspector' window in the tools drop-down to view the DPI. If I change the resolution to 300 in preview, it changes to 300, but that's beside the point.

(I can manually scale the image in preview after saving in R to pass the journal's standards, but I'd rather just understand how ggsave works so I can automate it)

I think this is a mac inspector issue though, isnt it ?
if you change the resolution to 300 in preview, does mac inspector reconsider its size assumptions? I'm not on a mac to verify anything, but on a windows pc, theres nothing problematic with the image. its 1500 pixes x 1500 pixels . it can therefore be rendered out to a medium at whatever dpi/physical size combinations are mathematically possible.
It will be for any application that opens it, to consider how it wants to render those 1500 pixels, whether to use one dpi or another. I think the png standard does support dpi metadata, but its not a requirement, its generally not a required thing...

or. in laymans terms, providing an image that is without a doubt 1500pixles by 1500 pixels, is providing an image that can be rendered at 300dpi over 5x5inches. (it could also be rendered out to other physical dimensions, but thats up to the publisher to decide)

Oh interesting. So the mac preview is probably opening it at the screen resolution (72 dpi) and so it suggests the size (in inches) is quite large. But in reality, it is 300 dpi at 5"x5". This sounds like a problem with the journal then. ( I realize I left out this context....journal is asking for higher dpi plots; the ones I sent in were >4000x4000 pixels...)

Yeah, actually I verified that ggsave recorded the dpi 300 metadata. So its entirely a mac inspector phenom.

library(magick)
img <- image_read("plot.png")
image_attributes(img)
                    property                             value
1                date:create         2021-03-23T19:28:03+00:00
2                date:modify         2021-03-23T19:28:04+00:00
3    png:IHDR.bit-depth-orig                                 8
4         png:IHDR.bit_depth                                 8
5   png:IHDR.color-type-orig                                 3
6        png:IHDR.color_type                       3 (Indexed)
7  png:IHDR.interlace_method                0 (Not interlaced)
8      png:IHDR.width,height                        1500, 1500
9                   png:pHYs x_res=11811, y_res=11811, units=1
10    png:PLTE.number_colors                               101
11                  png:sRGB      intent=0 (Perceptual Intent)

References
PNG Options and Extensions (PNG: The Definitive Guide) (libpng.org)
on line 9 - png:pHYs
we see that units is 1, so its meters. The image is 11811 pixels per meter left to right
its 1500 pixels wide, so thats a phyisical distance of

> 1500 / 11811 
[1] 0.1270003

0.127 meters.
which is
5Inches.

Amazing. Thank you so much! Hugely helpful.

1 Like

This is perhaps orthogonal to the original question, but does the journal accept .svg images? In that case they can render it at any dpi/size they need on their end.

That's interesting and potentially helpful. Image formats are pretty foreign to me. SVG files aren't listed in the journal's author resources, but it looks like the manuscript software allows svg files to be uploaded. Perhaps I'll offer that as a potential solution to the editor. Thank you!

If you don't have a good reason to have it be .png, I find that printing to PDFs and its true type font scaling makes one able to resize later at will, with no loss in resolution. I actually print to pdf at the dimensions desired, but then can share/scale later if needed. And you can convert later from pdf -> other formats at will.

df %>%
ggplot(aes(a, b)) +
geom_point() -> myplot

pdf(file = "plot.pdf", height = 5, width = 5)
print(myplot)
dev.off()

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.