Using a YAML header argument in knitr - r

I am making a set of slides using rmarkdown and the LaTeX option of outputting it to beamer.
I have two templates I use in my slides - one specific for the LaTeX options, and one pandoc template that I have modified to account for some additional feature of my slides.
I have defined an option in the YAML header called to_print which is a boolean TRUE/FALSE that I pass to the pandoc template that tells it to add a package and clean up the slides for printing.
I also want to use this variable to define the name of the files. The basic idea being that I want to have one .rmd file for my slides, and then just changing this one option to signify that it's for printing by students, or for me presenting.
I have figured out that I can pass the render function using the knit parameter in the YAML header, but I have to specify to_print = TRUE and set the condition in the ifelse() statement in the output_file correspondingly.
Currently I have:
---
title: "Introduction to R"
subtitle: "Reading and saving data in R"
date: '`r format(Sys.Date())`'
output:
beamer_presentation:
fonttheme: professionalfonts
highlight: tango
includes:
in_header: "../../templatefiles/beamer_header.tex"
template: "../../templatefiles/beamer_template.tex"
incremental: no
keep_tex: yes
slide_level: 3
theme: Warsaw
toc: yes
fontsize: 10pt
fontenc: T1
to_print: TRUE
knit: (function(inputFile, encoding) { rmarkdown::render(inputFile, encoding = encoding,
output_file = file.path(ifelse(TRUE,
gsub("\\..*","_handout.pdf", inputFile),
gsub("\\..*", ".pdf", inputFile)))) })
---
I would like to specify just one parameter that is then used to signify if this is a handout to be printed:
Pseudo-code:
to_print: TRUE
knit: (function(inputFile, encoding) {rmarkdown::render(inputFile, encoding = encoding,
output_file = file.path(ifelse(YAML_PARAM$to_print,
gsub("\\..*","_handout.pdf", inputFile),
gsub("\\..*", ".pdf", inputFile)))) })
Is this possible, or something equivalent that would let me have one .rmd file with a boolean to toggle presentation vs. printing?

You can use the rmarkdown::yaml_front_matter() function:
---
title: "Introduction to R"
subtitle: "Reading and saving data in R"
date: '`r format(Sys.Date())`'
output:
beamer_presentation:
fonttheme: professionalfonts
highlight: tango
includes:
in_header: "../../templatefiles/beamer_header.tex"
template: "../../templatefiles/beamer_template.tex"
incremental: no
keep_tex: yes
slide_level: 3
theme: Warsaw
toc: yes
fontsize: 10pt
fontenc: T1
to_print: TRUE
knit: (function(inputFile, encoding) { rmarkdown::render(inputFile, encoding = encoding,
output_file = file.path(ifelse(rmarkdown::yaml_front_matter(inputFile)$to_print,
gsub("\\..*","_handout.pdf", inputFile),
gsub("\\..*", ".pdf", inputFile)))) })
---

Related

How can I modify yaml instructions outside of the document I am rendering

I'd like to rmarkdown::render a R document without indicating the yaml options within the document itself.
Ideally that could be an argument on rmarkdown::render or knitr::spin like what you can do to pass params (see the Rmarkdown reference book). Typically I'd like author, date and the output options too.
I think this is possible because spining the following document without specifying anything I get the following output (so there must be a template of default args that I can hopefully change)
As an example, how could I do to render a document that would give me the same output as say the below (but of course without specifying the yaml in the document ie no yaml whatsoever in the document)
---
title: "Sample Document"
output:
html_document:
toc: true
theme: united
pdf_document:
toc: true
highlight: zenburn
---
#' # Title
Hello world
#+ one_plus_one
1 + 1
You can pass yaml options as parameters too. For example:
---
params:
title: "add title"
author: "add author"
output: pdf_document
title: "`r params$title`"
author: "`r params$author`"
---
This is my document text.
Then, in a separate R script:
rmarkdown::render("my_doc.rmd",
params=list(title="My title",
author="eipi10"))
You could cat a sink into a tempfile.
xxx <- "
#' # Title
Hello world
#+ one_plus_one
1 + 1
"
tmp <- tempfile()
sink(tmp)
cat("
---
title: 'Sample Document'
output:
html_document:
toc: true
theme: united
pdf_document:
toc: true
highlight: zenburn
---", xxx)
sink()
w.d <- getwd()
rmarkdown::render(tmp, output_file=paste(w.d, "myfile", sep="/"))

Including citation and references when using appendix on RMarkdown

I am working on RMarkdown to generate a report that includes an appendix after references. I have written the appendix on a different RMarkdown file and adapted my principal file to compile it. This is the code for my principal Rmd file that generates report:
---
bibliography: bb.bib
fontsize: 11pt
nocite: '#*'
output:
pdf_document:
includes:
after_body: Demo2.Rmd
keep_tex: yes
link-citations: true
---
\newpage
\section{Testing}\label{sec1}
```{r}
summary(cars)
```
\section{Demo}
This was done using #shiina and we will use some info from Section \ref{sec1} to do.
```{r}
summary(iris[,1:2])
```
\section{References}
The file bb.bib contains next references:
#article {shiina,
author = {Shiina, Takayuki and Birge, John R.},
title = {Stochastic unit commitment problem},
journal = {International Transactions in Operational Research},
volume = {11},
number = {1},
publisher = {Blackwell Publishing},
pages = {19--32},
year = {2004},
}
#book{groewe2001,
title={Stochastic unit commitment in hydro-thermal power production planning},
author={Gr{\"o}we-Kuska, N. and R{\"o}misch, W.},
year={2001},
series = { Preprints aus dem Institut f{\"u}r Mathematik },
publisher = { Humboldt-Universit{\"a}t zu Berlin, Institut f{\"u}r Mathematik },
}
Finally, my appendix Rmd file, Demo2.Rmd, contains this structure:
\appendix
\section*{Appendix}
\section{Additional info}
In this section we also follow #shiina to explain concepts.
Compilation works fine and generate document but issues are appearing in the appendix section. I used a reference with #shiina to cite something, but I am getting this output in the final report:
The circle in black shows that citation from bibliography is not working. Instead of #shiina, it should appear Shiina and Birge (2004). I have tried replacing Rmd file with a TeX file but it did not work.
Is it any way to correct that?, I do not know if after_body needs to be adjusted or what to do.
So, I did actually find a solution that does use some minor trickery.
---
bibliography: bb.bib
fontsize: 11pt
nocite: '#*'
output:
pdf_document:
keep_tex: true
includes:
after_body: Demo2.tex
link-citations: true
---
```{r,include=FALSE}
library(tidyverse)
rmarkdown::render('Demo2.Rmd')
a <- readChar('Demo2.tex', file.size('Demo2.tex'))
a <- a %>% str_remove('[[:space:]]*\\\\hypertarget[[\\w\\W]]+\\z') %>%
str_remove('\\A[[\\w\\W]]+begin.document.')
writeChar(a, 'Demo2.tex',eos = NULL)
```
\newpage
\section{Testing}\label{sec1}
```{r}
summary(cars)
```
\section{Demo}
This was done using #shiina and we will use some info from Section \ref{sec1} to do.
```{r}
summary(iris[,1:2])
```
\section{References}
And your Appendix-file:
---
bibliography: bb.bib
fontsize: 11pt
output:
pdf_document:
keep_tex: yes
link-citations: true
---
\appendix
\section*{Appendix}
\section{Additional info}
In this section we also follow #shiina to explain concepts.
# References
results in:
The way it works is to render the Demo2.Rmd- file before rendering the actual file and to keep the associated .tex- file.
Then the non included R-chunk cuts of all the parts we don't want to have at the end of the main file and overwrites the Demo2.tex-file.
What remains is the exact tex-code you need to have your references working.
Feels pretty dirty, but should work.

How can we pass pandoc_args to yaml header in rmarkdown?

I'm using rmarkdown to produce a word (.docx) report. I would like to change the header of the toc. This seems possible as pandoc_args can be passed as options in the yaml header in the case of a doc file (1). But I'm not doing it right. Could anyone provide a working example ?
(1) pandoc.args is included in the rmarkdown possible options and in the pandoc manual, there is a toc-title option
---
title: "yaml header"
author: "cedric"
output:
word_document:
toc: true
pandoc_args: toc-title="Table des matières"
---
# One section
# Another
This produces :
The title of the table of contents is document metadata, so you can set it with YAML metadata block.
---
title: "yaml header"
author: "cedric"
output:
word_document:
toc: true
toc-title: "Table des matières"
---
Or passed it in with the -M command-line flag.
---
title: "yaml header"
author: "cedric"
output:
word_document:
toc: true
pandoc_args: [
"-M", "toc-title=Table des matières"
]
---

R markdown YAML dynamic variables

In RMarkdown, I seem to be able to create 'some' dynamic variables in the YAML header, but not for others:
For instance, this works:
---
title:
"Some Title, `r format(Sys.time(), '%d %B, %Y')`"
...
---
But this does NOT.
---
...
pdf_document:
keep_tex: `r 'true'`
---
But this DOES (ie not dynamic).
---
...
pdf_document:
keep_tex: true
---
So how can I 'dynamically' assign the keep_tex to either true or false, what I want to do, is something like this:
---
...
pdf_document:
keep_tex: `r getOption('mypackage.keep_tex')`
---
I don't know if the template options can be set programmatically in the YAML header of the .Rmd file.
As an alternative, if you use rmarkdown::render to render your document, you may specify the output template (pdf_document), and then set template options (e.g. keep_tex) programmatically.
For example, if you have a .Rmd file called "test.Rmd" like this:
---
title:
"Some Title, `r format(Sys.time(), '%d %B, %Y')`"
---
...and some logical object which determines whether to keep the intermediate TeX file or not, e.g.
my_keep <- TRUE
...you may render the input file to PDF format and keep the TeX file like this:
render(input = "test.Rmd",
output_format = pdf_document(keep_tex = my_keep))

Rmarkdown directing output file into a directory

I found a really nice trick (link) to a function of knitr, where you can save your output html into an output folder and under a different filename.
The only thing you have to head to the header is the following:
title: "analysis"
author: "Me"
date: "`r format(Sys.time(), '%d %B, %Y, %H:%M')`"
knit: (function(inputFile, encoding) {
rmarkdown::render(inputFile,
encoding=encoding,
output_file=file.path(dirname(inputFile), out_dir, 'analysis.html')) })
output:
html_document:
number_sections: yes
toc: yes
This works on my Mac 'sometimes' very well, but sometimes it has problems to find the out_dir variable...
I first thought about executing the chunks first, so the variable is set... But this didn't solved the problem...
I also restarted R session and this didn't helped.
The last step was closing R, saving the workspace and after reopening R and loading workspace it works like a charm again.
I could not find the original post, where somebody recommended this trick...
EXACT WORKFLOW TO REPRODUCE
open new project, name it test in a new folder
create a r markdown document
change the header to:
---
title: "Untitled"
author: "Me"
date: "`r format(Sys.time(), '%d %B, %Y, %H:%M')`"
knit: (function(inputFile, encoding) {
rmarkdown::render(inputFile,
encoding=encoding,
output_file=file.path(dirname(inputFile), out_dir, 'analysis.html')) })
output:
html_document:
number_sections: yes
toc: yes
---
```{r write quant output files}
out_dir <- 'test'
if(!file.exists(out_dir)) {
dir.create(out_dir)
}
```
save the document as test.Rmd
click the knit button (html is now removed from the options of the button)
This will fail!
Close the project!
Click on save environment!
Open the Project and click knit!
Everything works.
execute rm(list=ls()) everything works afterwards again
You could try setting the out_dir variable in the function you are giving knit to render:
knit: (function(inputFile, encoding) {
out_dir <- 'test';
rmarkdown::render(inputFile,
encoding=encoding,
output_file=file.path(dirname(inputFile), out_dir, 'analysis.html')) })
I found it cumbersome to write the output-file name so I swapped the output_file to output_dir argument but kept the rest of the code. In this way my Rmarkdown is still knitted into a subdirectory but with the inputFile name. Also, if the directory does not exist, it is created
---
title: "title"
author: "gordon freeman"
date: "`r Sys.Date()`"
knit: (function(inputFile, encoding) {
out_dir <- "reports";
rmarkdown::render(inputFile,
encoding=encoding,
output_dir=file.path(dirname(inputFile), out_dir))})
---

Resources