I'm knitting an R Markdown file on macOS and I'm using knitr::opts_chunk$set(dev = c("png", "cairo_pdf"))
to save the output of plots as PNG and PDF files simultaneously. I'm also using the Cairo PDF library since it can embed fonts correctly by default (see here)
When I knit and create a plot that uses a custom font, knitr correctly saves both the PNG and PDF files using Cairo:
However, in the actual knitted R Markdown document, R complains about missing fonts and provides dozens of warnings. This is odd, since it is working just fine behind the scenes.
Here's a MWE:
---
title: "So many warnings?"
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(fig.path = "fig/", # Save images to a subdirectory
echo = FALSE, # Hide code for now
dpi = 300, # High resolution PNGs
# Save all figures as Cairo PDFs and PNGs
dev = c("png", "cairo_pdf"),
dev.args = list(png = list(type = "cairo")))
```
```{r load-libraries}
library(ggplot2)
```
```{r warningless-plot}
# This will save two files in the fig/ folder, both saved using Cairo:
# - fig/warningless-plot-1.png
# - fig/warningless-plot-1.pdf
ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point()
```
```{r warningful-plot}
# This will save two files in the fig/ folder, both saved *correctly* using Cairo:
# - fig/warningful-plot-1.png
# - fig/warningful-plot-1.pdf
# However, rmarkdown or knitr or something in the pipeline gets mad and throws
# a ton of warnings.
ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point() +
theme_grey(base_family = "Comic Sans MS")
```
The figures themselves are saved correctly, but the HTML output is full of these warnings:
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Comic Sans MS' not found in PostScript font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Comic Sans MS' not found in PostScript font database
Right now my solution is to add warning=FALSE
to the chunk options for warningful-plot
and all other chunks that generate plots with custom fonts. I'd like to know why these extra warnings are happening, though, and if there's a way to avoid getting warnings in the first place.
knitr is an engine for dynamic report generation with R. It is a package in the programming language R that enables integration of R code into LaTeX, LyX, HTML, Markdown, AsciiDoc, and reStructuredText documents. The purpose of knitr is to allow reproducible research in R through the means of literate programming.
The first code chunk: ```{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE) ``` is used to specify any global settings to be applied to the R Markdown script. The example sets all code chunks as “echo=TRUE”, meaning they will be included in the final rendered version.
When you run render , R Markdown feeds the . Rmd file to knitr, which executes all of the code chunks and creates a new markdown (. md) document which includes the code and its output. The markdown file generated by knitr is then processed by pandoc which is responsible for creating the finished format.
Answering my own question here…
According to a couple issues on GitHub (at knitr and hrbrthemes), this happens because knitr invisibly uses a null PDF device (pdf(NULL)
) in the background when actually knitting. The default pdf()
graphics device in R can't handle custom fonts, though, hence the warnings. Even though none of the visible graphics ever go through the base pdf()
device, they still go through it invisibly I guess.
When knitting using dev = 'png'
, knitr will use an invisible png()
device and no warnings will be thrown. It seems that using a cairo_pdf
device at the same time breaks this and forces knitr to go back to an invisible, custom-font-less pdf()
device.
We can fix this by forcing knitr to use an invisible png()
device instead, based on this comment here:
# Use invisible NULL png() device
options(device = function(file, width, height) {
png(tempfile(), width = width, height = height)
})
# knit options, including `dev = c("png", "cairo_pdf")`
knitr::opts_chunk$set(fig.path = "fig/", # Save images to a subdirectory
echo = FALSE, # Hide code for now
dpi = 300, # High resolution PNGs
# Save all figures as Cairo PDFs and PNGs
dev = c("png", "cairo_pdf"),
dev.args = list(png = list(type = "cairo")))
That options(device = ...)
incantation makes the warnings go away.
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