如何在R Markdown中使用Cairo PNG

时间:2019-03-05 18:27:23

标签: r ggplot2 r-markdown knitr cairo

使用Cairo保存R图形(see here, for example)有很多优点。例如,保存PDF时,cairo_pdf设备会正确嵌入自定义字体。

使用带有cairo_pdf的基于ggplot的图形,很容易使用ggsave()图形设备:

library(ggplot2)

ugly_plot <- ggplot(mtcars, aes(x = wt, y = mpg)) +
  geom_point() +
  labs(title = "Some data about cars") +
  theme_gray(base_family = "Papyrus")
ugly_plot

ggsave(ugly_plot, filename = "ugly_plot.pdf", 
       width = 4, height = 2.5, device = cairo_pdf)

在R Markdown中将cairo_pdf设备与knitr一起使用也很容易-将dev: cairo_pdf添加到YAML前端:

---
title: "Cairo stuff"
output:
  pdf_document:
    dev: cairo_pdf
---

```{r make-ugly-plot, fig.width=4, fig.height=2.5}
library(ggplot2)

ugly_plot <- ggplot(mtcars, aes(x = wt, y = mpg)) +
  geom_point() +
  labs(title = "Some data about cars") +
  theme_gray(base_family = "Papyrus")
ugly_plot
```

PDF output

Cairo correctly deals with DPI起,使用基于开罗的PNG也有优势。如果将具有高DPI的正常保存的PNG放置到Word或PowerPoint文件中,则图形的尺寸会被夸大且不准确。如果将具有相同高DPI的基于Cairo的PNG放入Word中,则尺寸是正确的:

Weird Word dimensions

使用ggsave()可以很容易地将ggplot输出保存为高分辨率Cairo PNG,但是语法与另存为Cairo PDF稍有不同。我们没有指定设备,而是指定类型:

ggsave(ugly_plot, filename = "ugly_plot.png", 
       width = 4, height = 2.5, dpi = 300, type = "cairo")

在Word或PowerPoint中放置该文件的效果很好,并且所有文件都可以在高分辨率下正确调整大小。

这种对尺寸的误解会在编织为HTML或Word时延续到R Markdown中。编织时最好使用type = "cairo",但要在R Markdown中复制此dpi = 300, type = "cairo"会更困难。开罗库包含Cairo::CairoPNG()之类的设备,但是ggsave(..., type = "cairo")不使用此设备。它使用R的标准PNG设备,但已启用Cairo支持。

通过在块选项中添加dpi=300可以使图形变得很容易,但是我无法让knitr使用启用了type = cairo的内置PNG设备。我尝试过天真地将type: cairo添加到YAML元数据中,但这并不奇怪。 Knitr生成的PNG不使用Cairo,并且比预期的要大得多(并且在HTML和Word文档中是巨大的)。

---
title: "Cairo stuff"
output:
  html_document: 
    self_contained: no  # to see resulting figure as a file
    dev: png
    type: cairo  # this doesn't do anything
---

```{r make-ugly-plot, fig.width=5, fig.height=3.5, dpi=300}
library(ggplot2)

ugly_plot <- ggplot(mtcars, aes(x = wt, y = mpg)) +
  geom_point() +
  labs(title = "Some data about cars") +
  theme_gray(base_family = "Papyrus")
ugly_plot
```

总而言之,我正在寻找一种方法来使用您从knitr中的ggsave(..., filename = "blah.png", dpi = 300, type = "cairo")获得的相同输出。有办法吗?

---
title: "Something"
output:
  pdf_document:
    dev: cairo_pdf  # yay Cairo output
  html_document:  # What needs to go here?
    dev: png
    type: cairo
---

2 个答案:

答案 0 :(得分:8)

有条件地在设置块中进行操作,而不是尝试在yaml标头中进行操作。

if (!knitr::is_latex_output()) {
  knitr::opts_chunk$set(dpi = 300, dev.args = list(type = "cairo"))
})

我现在已经在一些文档中使用了它。 注意:我仅将其用于从R命令行执行rmarkdown::render(...)的文档。

答案 1 :(得分:0)

作为在每个文件顶部使用一段代码的@rmflight's answer的替代方法,这可以在外壳包装程序或Makefile中实现,该程序使用{{1 }}:

rmarkdown::render()