简体   繁体   English

如何在 R Markdown 中使用 Cairo PNG

[英]How to use Cairo PNGs in R Markdown

There are many advantages to using Cairo to save R graphics ( see here, for example ).使用 Cairo 保存 R 图形有很多优点( 例如,请参见此处)。 When saving PDFs, for instance, the cairo_pdf device correctly embeds custom fonts.例如,在保存 PDF 时, cairo_pdf设备会正确嵌入自定义字体。

Using the cairo_pdf graphics device is easy with ggplot-based graphics with ggsave() :使用带有ggsave()的基于cairo_pdf图形可以轻松使用cairo_pdf图形设备:

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)

Using the cairo_pdf device in R Markdown with knitr is also easy—add dev: cairo_pdf to the YAML front matter:在 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输出

There are also advantages to using Cairo-based PNGs, since Cairo correctly deals with DPI .使用基于开罗的 PNG 也有优势,因为开罗正确处理 DPI If you place a normally-saved PNG with a high DPI into a Word or PowerPoint file, the dimensions of the figure are exaggerated and not accurate.如果将正常保存的高DPI的PNG放入Word或PowerPoint文件中,图的尺寸被夸大,不准确。 If you place a Cairo-based PNG with the same high DPI into Word, the dimensions are correct:如果将具有相同高 DPI 的基于开罗的 PNG 放入 Word,则尺寸是正确的:

奇怪的词尺寸

Saving ggplot output as high resolution Cairo PNGs is easy with ggsave() , but the syntax is slightly different from saving as Cairo PDFs.使用ggsave() ggplot 输出保存为高分辨率开罗 PNG 很容易,但语法与保存为开罗 PDF 略有不同。 Instead of specifying a device, we specify type:我们指定类型而不是指定设备:

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

Placing that file in Word or PowerPoint works great and everything is sized correctly at high resolution.将该文件放在 Word 或 PowerPoint 中效果很好,并且所有内容都以高分辨率正确调整大小。

This misinterpretation of dimensions carries over into R Markdown when knitting to HTML or Word.当编织到 HTML 或 Word 时,这种对尺寸的误解会延续到 R Markdown 中。 It'd be great to have knitr use type = "cairo" when knitting, but replicating this dpi = 300, type = "cairo" in R Markdown, however, is more difficult.在编织时让 knitr 使用type = "cairo"会很棒,但是在 R Markdown 中复制这个dpi = 300, type = "cairo"更困难。 The Cairo library includes devices like Cairo::CairoPNG() , but ggsave(..., type = "cairo") doesn't use this device. Cairo 库包括Cairo::CairoPNG() ,但ggsave(..., type = "cairo")不使用此设备。 It uses R's standard PNG device, but with Cairo support turned on.它使用 R 的标准 PNG 设备,但开启了 Cairo 支持。

Making the figure high resolution is easy enough with adding dpi=300 to the chunk options, but I can't get knitr to use the built-in PNG device with type = cairo enabled.通过将dpi=300添加到块选项中,使图形高分辨率很容易,但是我无法让 knitr 使用启用type = cairo的内置 PNG 设备。 I tried naively adding type: cairo to the YAML metadata, but it unsurprisingly doesn't work.我尝试天真地将type: cairo添加到 YAML 元数据中,但不出所料,它不起作用。 The PNG that knitr generates doesn't use Cairo and is much larger than expected (and is gigantic in HTML and Word documents). 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
```

In sum, I'm looking for a way to use the same output you'd get from ggsave(..., filename = "blah.png", dpi = 300, type = "cairo") in knitr.总之,我正在寻找一种方法来使用您从ggsave(..., filename = "blah.png", dpi = 300, type = "cairo")获得的相同输出。 Is there a way to do this?有没有办法做到这一点?

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

Use knitr options, not the YAML header.使用knitr选项,而不是 YAML 标头。

You can use knitr options to change the type of a specific device (Yihui's recommendation):您可以使用knitr选项来更改特定设备的类型(Yihui 的推荐):

knitr::opts_chunk$set(dev.args = list(png = list(type = "cairo")))

Alternately, you could do it conditionally based on the output:或者,您可以根据输出有条件地执行此操作:

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

I've used this on a couple of documents now.我现在已经在几个文档中使用了它。 Note : I've only used this for documents doing rmarkdown::render(...) from the R command line.注意:我只将它用于从 R 命令行执行rmarkdown::render(...)文档。

作为使用每个文件顶部的一段代码替代@rmflight 的答案,这可以在 shell 包装器或Makefile ,后者使用rmarkdown::render()的可选参数编​​织 Rmarkdown 文件:

R -e 'rmarkdown::render("foo.Rmd", "pdf_document", output_file="foo.pdf", runtime = "static", output_options = list(dpi = 300, dev.args = list(type = "cairo")))'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM