I'm having an r-scipt that is generaing a PDF
in the following way...
baseplot
and ggplot
. The graphs are generated with pdf
device. The reason I'm using pdf
is that I need to embed fonts (to use custom font in tex labels).Sweave
that generates .tex
to gather all that graphs together.MikTeX
to generate PDF.It turns out that 75-95% of time needed to generate a graph is taken by embed_fonts
call. Is there a way to do less embed_fonts
(that seems to be a wrapper for ghostscript) calls? The ideal vatiant is to embed call only one time. Is that possible?
Maybe you could use the cairo_pdf
device that should embed the fonts.cairo_pdf
seems slower than pdf
but faster than pdf + embedFonts
.
Of course embedding the fonts in the final pdf document only would be a better solution...
library(microbenchmark)
res_pdf <- microbenchmark({
f = tempfile(fileext = '.pdf')
pdf(f); pairs(iris); dev.off()
})
res_embed <- microbenchmark({
f = tempfile(fileext = '.pdf')
pdf(f); pairs(iris); dev.off()
embedFonts(f)
})
res_cairo <- microbenchmark({
f = tempfile(fileext = '.pdf')
cairo_pdf(f); pairs(iris); dev.off()
})
res_pdf
#> Unit: milliseconds
#> min lq mean median uq max neval
#> 16.67764 17.0388 18.05949 17.32904 18.18776 60.2542 100
res_embed
#> Unit: milliseconds
#>
#> min lq mean median uq max neval
#> 250.046 252.7647 257.4749 255.2785 259.4858 303.0072 100
res_cairo
#> Unit: milliseconds
#>
#> min lq mean median uq max neval
#> 84.25745 86.60512 88.42902 88.36698 89.5705 111.5881 100
An alternative solution would be to output your plots as TikZ using the excellent tikzDevice
package.
From an rmarkdown document we can include a knitr chunk with the device set to tikz
.
---
output:
pdf_document:
latex_engine: xelatex
header-includes:
- \renewcommand{\familydefault}{\sfdefault}
- \usepackage{tikz}
---
```{r setup, include=FALSE}
library(tikzDevice)
# setting the package options so that the font metrics are calculated correctly
options(
tikzLatexPackages = c(
getOption("tikzLatexPackages"),
"\\renewcommand{\\familydefault}{\\sfdefault}"
)
)
```
# My plot
This text will be set in the default *sans serif* and so will the text found
within the chart below.
```{r, echo=FALSE, dev='tikz'}
pairs(iris)
```
You can replace my \renewcommand{\familydefault}{\sfdefault}
with whatever latex command you require to set your selected font, such as \usepackage{charter}
. Just note that you must escape the \
as in my example above.
You may want to generate all your plots in advance with another script given you have so many, instead of knitting inline at the time of document generation. I do this for a mass run of reports (1,000+) each with about 20 plots.
# a more simple example due to output size
library(tikzDevice)
mpg <- mtcars$mpg
tikz(file = "example.tex"); hist(mpg); dev.off()
% Created by tikzDevice version 0.10.1.2 on 2018-02-21 23:32:57
% !TEX encoding = UTF-8 Unicode
\begin{tikzpicture}[x=1pt,y=1pt]
\definecolor{fillColor}{RGB}{255,255,255}
\path[use as bounding box,fill=fillColor,fill opacity=0.00] (0,0) rectangle (216.81,216.81);
\begin{scope}
\path[clip] ( 0.00, 0.00) rectangle (216.81,216.81);
\definecolor{drawColor}{RGB}{0,0,0}
\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.20] at (120.41,188.07) {\bfseries Histogram of mpg};
\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (120.41, 15.60) {mpg};
\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 10.80,114.41) {Frequency};
\end{scope}
\begin{scope}
\path[clip] ( 0.00, 0.00) rectangle (216.81,216.81);
\definecolor{drawColor}{RGB}{0,0,0}
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 54.47, 61.20) -- (186.34, 61.20);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 54.47, 61.20) -- ( 54.47, 55.20);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 80.85, 61.20) -- ( 80.85, 55.20);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (107.22, 61.20) -- (107.22, 55.20);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (133.59, 61.20) -- (133.59, 55.20);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (159.96, 61.20) -- (159.96, 55.20);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (186.34, 61.20) -- (186.34, 55.20);
\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 54.47, 39.60) {10};
\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 80.85, 39.60) {15};
\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (107.22, 39.60) {20};
\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (133.59, 39.60) {25};
\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (159.96, 39.60) {30};
\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (186.34, 39.60) {35};
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 65.14) -- ( 49.20,163.67);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 65.14) -- ( 43.20, 65.14);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 81.56) -- ( 43.20, 81.56);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 97.98) -- ( 43.20, 97.98);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,114.40) -- ( 43.20,114.40);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,130.83) -- ( 43.20,130.83);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,147.25) -- ( 43.20,147.25);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,163.67) -- ( 43.20,163.67);
\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80, 65.14) {0};
\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80, 81.56) {2};
\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80, 97.98) {4};
\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,114.40) {6};
\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,130.83) {8};
\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,147.25) {10};
\end{scope}
\begin{scope}
\path[clip] ( 49.20, 61.20) rectangle (191.61,167.61);
\definecolor{drawColor}{RGB}{0,0,0}
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 54.47, 65.14) rectangle ( 80.85,114.40);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 80.85, 65.14) rectangle (107.22,163.67);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (107.22, 65.14) rectangle (133.59,130.83);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (133.59, 65.14) rectangle (159.96, 81.56);
\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (159.96, 65.14) rectangle (186.34, 97.98);
\end{scope}
\end{tikzpicture}
N.B. This is not a complete
.tex
file and is rather designed to be brought in using\input{example.tex}
or otherwise embedded into a complete document. Also, be mindful of the font metric calculations, the saved.tex
file may render strangely with different fonts if the metrics are significantly out.
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