I need to export graphics from R for the use in different publications formats, i.e., scientific poster, Journal Articel, Powerpoint presentation. As Long as I'm not aware of using R-Markdown and Latex, Or Sweave to produce pdf slides, i need to use Microsoft applications.
I do graphics in R with ggplot2.
My MWE
df1 <- expand.grid(Year = c(2000, 2010),
Treat = c("TreatA","TreatB"),
Location = c("Berlin", "Munich", "Kansas", "Paris"),
rep = c(1,2,3,4,5,6,7,8,9,10))
df1 <- cbind(df1,
Var1 = runif(160, -10,25) + rnorm(160,8,4))
My Graphics Code:
p1 <- ggplot(aes(y = Var1, x = Treat, na.rm=TRUE, fill=Location), data = df1) +
stat_boxplot(geom ='errorbar', width= 0.5) +
geom_boxplot(outlier.shape = 1, outlier.size = 2, linetype="solid", size = 1) +
facet_grid( Year ~ Location) +
scale_y_continuous(limits=c(-20,60)) +
scale_fill_manual(values=c("#E69F00", "#009E73", "#0072B2", "#D55E00")) +
ylab("Magic Skills") +
xlab("Magic Juice") +
theme(text=element_text(family="Arial", size=18),
axis.text.x = element_text(angle = 30, hjust = 1),
line=element_line(size=1),
rect=element_rect(colour="red", size=1),
panel.background=element_rect(colour="black",fill="white", size=1),
strip.background=element_rect(colour="dark grey", fill="black"),
strip.text=element_text(face="bold", colour="white"),
panel.grid.major=element_blank(),
panel.grid.minor=element_blank(),
legend.position="none");p1
How I save the graph:
ggsave(p1, file="Results/Figures/Abb2_Boxplots_LarvenPuppen2.svg", width=35, height=20, units = "cm", dpi=500)
I set the font size with "theme(text=element_text(family="Arial", size=18)" for the whole graph. During ggsave I adjust the height and width, for the Poster the height should be 20 cm and width 35 cm. I save in .svg since I made best experience with the quality of the graph, furthermore I can edit anything at anytime in Inkscape, that's great!
So far so good, yet, it appears, that the text is by no means 18 pt, later in the powerpoint-poster, after exporting the graph (without editing!) as .png from Inkscape. It is even not 20 x 35 cm, I found that i loose about 5 cm or more during the saving and export process.
I guess R is doing write, when i say save 20x35 cm R will do it. Where in the whole process were my settings changed, and how can I handle it?
Best regards, Pharcyde
There's a few things to consider:
Here's a pure grid example that illustrates the second point,
library(grid)
g <- grobTree(rectGrob(), textGrob("test", gp=gpar(fontsize=12)))
ggplot2::ggsave("size.svg", g, width = 10, height=10, units = "in")
tmp <- readLines("size.svg")
grep("test", tmp, value = TRUE)
# "<text x='350.33' y='364.30' style='font-size: 12.00px; font-family: Arial;' textLength='19.34px' lengthAdjust='spacingAndGlyphs'>test</text>"
grep("viewBox", tmp, value = TRUE)
# "<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 720.00 720.00'>"
So short answer is that the svg produced by R (svglite here) contains a seemingly consistent font size (12px), but the 10 inches is interpreted as 720px regardless of dpi. Looking at the source this 72 factor comes from R graphics conventions (typically devices follow the pdf device, which defaults to a 72DPI resolution. Why this is not affected by the various dpi/res/pointsize parameters is a mystery to me).
The gridSVG package by-passes the usual graphics engine system, and appears to produce more straight-forward sizes,
library(gridSVG)
gridsvg("size.svg", res = 1000, width=10, height=5)
grid.draw(g)
dev.off()
tmp <- readLines("size.svg")
grep("viewBox", tmp, value = TRUE)
# "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"10000px\" height=\"5000px\" viewBox=\"0 0 10000 5000\" version=\"1.1\">"
though this time the font size is scaled (it is 12 for the default 72DPI resolution),
grep("font-size", tmp, value = TRUE)
# "<text x=\"0\" y=\"0\" id=\"GRID.text.41.1.1.text\" text-anchor=\"middle\" font-size=\"166.67\" fill=\"rgb(0,0,0)\" fill-opacity=\"1\">"
On the ggplot2 side, things get even murkier because of some built-in settings for the inheritance of theme elements, rel()
ative scaling, scales, that may or may not be documented (and have changed in the past IIRC).
"18pt" in an SVG is not the same as 18pt on a printed page.
One point ("pt") in a CSS style attribute has been defined - like in the printing industry - as 1/72 of an inch. However in CSS, an inch is not a real-world inch, but instead it is 96 "CSS pixels".
That dpi of 96, is a arbitrary value chosen a long time ago. Computer monitors aren't 96 pixels per inch any more (if any ever were).
If you want something to match the real world - for example one real inch on a printed page or screen - you will have to test your environment and output method, and apply a scaling factor to your SVG units. Or to your conversion technique.
Here is how it worked:
p1 <- ggplot(aes(y = Var1, x = Treat, na.rm=TRUE, fill=Location), data = df1) +
stat_boxplot(geom ='errorbar', width= 0.5) +
geom_boxplot(outlier.shape = 1, outlier.size = 2, linetype="solid", size = 1) +
facet_grid( Year ~ Location) +
scale_y_continuous(limits=c(-20,60)) +
scale_fill_manual(values=c("#E69F00", "#009E73", "#0072B2", "#D55E00")) +
ylab("Magic Skills") +
xlab("Magic Juice") +
theme(text=element_text(family="Arial", size=36*96/72),
axis.text.x = element_text(angle = 30, hjust = 1),
line=element_line(size=1),
rect=element_rect(colour="red", size=1),
panel.background=element_rect(colour="black",fill="white", size=1),
strip.background=element_rect(colour="dark grey", fill="black"),
strip.text=element_text(face="bold", colour="white"),
panel.grid.major=element_blank(),
panel.grid.minor=element_blank(),
legend.position="none");p1
ggsave(p1, file="Results/Figures/Trial.svg", width=35*1.25, height=20*1.25, units="cm", dpi=96)
With this code, I got an 35x20 cm plot both in Inkscape and in Powerpoint. Furthermore the size of the letters was pretty much the size of letters in powerpoint.
This time I chose letter size 36pt, since this is more useful for Poster-presentations. I did not make further trials with changing the dpi.
Here my findings so far:
R uses 72 dpi by default, the formula: size * new resolution DPI / 72 DPI, e.g.: 36 * 96/72, delivers almost similar pt sizes in Microsoft office documents. Irrespective of both the dpi settings used in ggsave as well as the height and width settings.
10 cm specified in R via ggsave() correspond to 8.060 cm in Inkscape. Multiplying the admired width/height by 1.25 delivers correct image sizes in Inkscape and also in MS Office, irrespective of the dpi set in the Export settings.
Something that makes me still wonder is that although I made the same settings for font size for the WHOLE plot via "text=element_text(family="Arial", size=36*96/72)" Label titles are taller than tick labels or text in the facet boxes.
best wishes, Pharcyde
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With