【问题标题】:Export Graphics with exact size and font size导出具有精确大小和字体大小的图形
【发布时间】:2017-04-11 12:20:21
【问题描述】:

我需要从 R 中导出图形以用于不同的出版物格式,即科学海报、期刊论文、Powerpoint 演示文稿。只要我不知道使用 R-Markdown 和 Latex 或 Sweave 来制作 pdf 幻灯片,我就需要使用 Microsoft 应用程序。

我用 ggplot2 在 R 中做图形。

我的 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 中编辑任何内容,这很棒!

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

我猜 R 正在写,当我说保存 20x35 厘米时,R 会写。我的设置在整个过程中哪里发生了变化,我该如何处理?

最好的问候, 药丸

【问题讨论】:

    标签: r svg ggplot2


    【解决方案1】:

    有几点需要考虑:

    • 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 生成的 svg(此处为 svglite)包含看似一致的字体大小(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()ative 缩放、比例,可能会或可能不会记录(并且在过去的 IIRC 中已更改),因此事情变得更加模糊.

    【讨论】:

      【解决方案2】:

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

      CSS 样式属性中的一个点(“pt”)已被定义为 - 就像在印刷行业中一样 - 为 1/72 英寸。然而在 CSS 中,一英寸并不是现实世界中的英寸,而是 96 个“CSS 像素”。

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

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

      【讨论】:

      • 如果我理解正确,它应该可以工作,如果我以 96 dpi 导出图形,从 R 到 SVG,从 Inkscape 到 PNG。我试过了,但失败了。
      • 我读到 R 的默认分辨率是 72 dpi。使用 size = 18*96/72,并通过 ggsave(..., dpi=96) 导出以这种方式工作,字母的大小或多或少与 18pt 相同,但是整个图形的大小是太小,即小于 ggsave() 命令中设置的值。
      • 我发现,在 ggsave() 中设置不同的 dpi(不改变宽度和高度)不会改变 Inkscape 中绘图的大小
      • 使用 ggsave() 设置 width=1, height=1 units="cm" 保存,给出宽度=4.755 cm 和高度= 5.169 cm 的图。对于 10x10 厘米设置,Inkscape 中的宽度和高度为 8.060 x 8.060 厘米
      • 抱歉,我无法针对 R 提供更具体的建议。我不是 R 的用户。
      【解决方案3】:

      这是它的工作原理:

      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. 通过 ggsave() 在 R 中指定的 10 厘米对应于 Inkscape 中的 8.060 厘米。 将喜欢的宽度/高度乘以 1.25 可以在 Inkscape 和 MS Office 中提供正确的图像尺寸,而与导出设置中设置的 dpi 无关。

      让我仍然想知道的是,尽管我通过“text=element_text(family="Arial", size=36*96/72)" 为整个图的字体大小设置了相同的设置 标签标题高于分面框中的刻度标签或文本。

      最好的祝愿, 药丸

      【讨论】:

      • 也许工作流程中的某些东西的默认 DPI 为 90。这可能是磨损 1.25 的因素。
      【解决方案4】:

      ggplot 使用的字体大小与 word 中的字体大小相匹配,问题是图形在保存期间、导入期间或同时调整大小。对我来说最好的解决方案是将图形窗口设置为文档中图形的大小(5.33" x 4" 通常在 Word 中看起来不错;7.5" x 10" 用于 4:3 PowerPoint),然后保存那个尺寸的图。您可能需要使用文件类型(.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()
      

      【讨论】:

        猜你喜欢
        • 2013-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-23
        • 2012-01-18
        相关资源
        最近更新 更多