导出具有确切大小和字体大小的图形

时间:2017-04-11 12:20:21

标签: r svg ggplot2

我需要从R导出图形以用于不同的出版物格式,即科学海报,Journal Articel,Powerpoint演示。只要我不知道使用R-Markdown和Latex,或者Sweave生成pdf幻灯片,我就需要使用Microsoft应用程序。

我在R中用ggplot2做图形。

我的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))

我的图形代码:

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

我如何保存图表:

ggsave(p1, file="Results/Figures/Abb2_Boxplots_LarvenPuppen2.svg", width=35, height=20, units = "cm", dpi=500) 

我为整个图形设置了字体大小“theme(text = element_text(family =”Arial“,size = 18)”。 在ggsave期间,我调整高度和宽度,海报的高度应为20厘米,宽度为35厘米。我保存.svg,因为我对图表的质量有了最好的体验,而且我可以在Inkscape中随时编辑任何内容,这太棒了!

到目前为止,看起来很好,但是,在将图形(没有编辑!)从Inkscape导出为.png之后,文本绝不是18 pt,后来在powerpoint-poster中。它甚至不是20 x 35厘米,我发现在保存和出口过程中我松了大约5厘米或更多。

我猜R正在写,当我说保存20x35 cm R就可以了。在整个过程中,我的设置发生了变化,我该如何处理呢?

祝你好运, Pharcyde

4 个答案:

答案 0 :(得分:3)

需要考虑以下几点:

  • SVG units - 请注意有关用户单元的讨论,以及pt vs px
  • 网格图形参数及其如何被设备解释
  • ggplot2,以及其主题设置如何影响字体大小

这是一个纯粹的网格示例,用于说明第二点,

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'>"

如此简短的回答是由R(svglite这里)生成的svg包含看似一致的字体大小(12px),但无论dpi如何,10英寸都被解释为720px。查看the source this 72 factor来自R图形约定(通常设备遵循pdf设备,默认为72DPI分辨率。为什么这不受各种dpi / res / pointsize参数的影响对我来说是一个谜。)

gridSVG软件包绕过通常的图形引擎系统,看起来产生更直接的尺寸,

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\">"

虽然这次缩放了字体大小(默认72DPI分辨率为12),

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\">"                                       

在ggplot2方面,由于主题元素的继承的一些内置设置,rel()缩放,缩放,可能会或可能不会记录(并且在过去已更改),因此事情变得更加模糊这个)。

答案 1 :(得分:1)

SVG中的“18pt”与打印页面上的18pt不同。

CSS样式属性中的一点(“pt”)已经定义 - 就像在印刷行业中一样 - 为1/72英寸。但是在CSS中,英寸不是真实的英寸,而是96英寸的CSS像素。

96的dpi是很久以前选择的任意值。电脑显示器不再是每英寸96像素(如果有的话)。

如果您想要与现实世界相匹配的东西 - 例如打印页面或屏幕上的一个真实英寸 - 您将必须测试您的环境和输出方法,并将缩放因子应用于您的SVG单位。或者转换技术。

答案 2 :(得分:1)

以下是它的工作原理:

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) 

使用此代码,我在Inkscape和Powerpoint中都得到了一个35x20厘米的图。 此外,字母的大小几乎与powerpoint中字母的大小相同。

这次我选择了36pt的字母大小,因为这对于海报展示更有用。我没有进一步试验改变dpi。

到目前为止我的调查结果:

  1. R默认使用72 dpi,公式为:尺寸*新分辨率DPI / 72 DPI , 例如:36 * 96/72,在Microsoft Office文档中提供几乎相似的pt大小。无论ggsave中使用的dpi设置以及高度和宽度设置如何。

  2. R via ggsave()中指定的10 cm对应于Inkscape中的8.060 cm。 将所欣赏的宽度/高度乘以1.25 可在Inkscape和MS Office中提供正确的图像大小,无论在导出设置中设置的dpi如何。

  3. 让我仍然感到奇怪的是,虽然我通过&#34; text = element_text(family =&#34; Arial&#34;,size = 36 * 96 /)对整个剧情的字体大小设置了相同的设置72)&#34; 标签标题高于刻度标签或方面框中的文本。

    最好的祝福, Pharcyde

答案 3 :(得分:0)

ggplot所使用的字体大小与单词中的字体大小相匹配,问题是在保存过程中,导入过程中或在两者期间都调整了图形的大小。对我来说,最好的解决方案是将图形窗口设置为文档中图形的大小(在Word中通常为5.33“ x 4”;对于4:3 PowerPoint,则为7.5“ x 10”),然后保存那个尺寸的数字。您可能需要处理文件类型(.tif在PowerPoint中不能很好地播放,并且由于某些原因会被调整大小)。就是说,如果您使用此方法,并确保从R导出图形后图形未调整大小,则其字体大小将与制作ggplot时的字体大小完全相同。

这是我使用的代码,

dev.new(width = 10, height = 7.5, unit="in", noRStudioGD = T);last_plot() #Set new windo size and replot whatever plot you just made. 
ggsave("workingdirectory/plot.png",width = dev.size()[1],height = dev.size()[2]);dev.off() #Save the plot and set the size using `dev.siz()` so you don't have to ever change that part and cannot possibly have a typo. 

这是一个带有输出的完整示例,您可以将其引入4:3 PowerPoint中并亲自查看其工作原理。

measure1<-as.numeric(1:50)
category<-rep(c("a","b","c","d","e"),each=10)

df<-data.frame(measure1,category)


library(ggplot2)
library(extrafont)
ggplot(df, aes(x = category , y = measure1, fill = category, colour = category)) +
  geom_boxplot(outlier.shape = NA, show.legend = F, notch = F) +
  geom_point(aes(),size = 3, shape=16, colour="white", alpha=.6) +
  stat_summary(fun.y=mean, show.legend = FALSE, geom="point", shape=18, size=5, colour = "white", na.rm = TRUE) +
  ylab("Measure") +
  xlab("Category") +
  ggtitle("") +
  scale_y_continuous (limits = c(0,50), expand = c(0,0), breaks=seq(0,50,5))+
  scale_x_discrete(limits=c("a","b","c","d","e")) +
  scale_fill_manual(values = rep("black",5))+
  scale_colour_manual(values = rep("white",5))+
  theme_bw() +
  theme (text=element_text(size=24,  family="Times New Roman"),
         axis.title.y=element_text(size=24, vjust=2, colour="white"),
         axis.title.x=element_text(size=24, hjust=0.5, colour="white"),
         panel.border = element_blank(),
         plot.title=element_blank(),
         plot.margin = unit(c(.5, .5, .5, .5), "cm"),
         panel.background = element_rect(fill = "black"),
         plot.background = element_rect(fill = "black"),
         panel.grid.major = element_blank(),
         panel.grid.minor = element_blank(),
         legend.position = "none",
         axis.ticks = element_line(size=0.8, colour = "white"),
         axis.ticks.length=unit(0.2,"cm"),
         axis.text.x=element_text(colour="white",size=24,angle=0,hjust=.5),
         axis.text.y=element_text(colour="white",size=24),
         axis.line = element_line(colour="white", size=0.8, lineend = "square"))

dev.new(width = 10, height = 7.5, unit="in", noRStudioGD = T);last_plot()
ggsave("C:/Users/s39f171/Documents/plot.png",width = dev.size()[1],height = dev.size()[2]);dev.off()