Rmarkdown directing output file into a directory - r

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))})
---

Related

Dynamically Name .Rmd Output File Based on Variable

Say I have an .Rmd file named "Process.Rmd", and within one chunk of the file I have a variable such as clientName <- "client AAA". Can I change the output filename from Process.pdf to Process_AAA.pdf? Specifically, the goal would be that I can simply change the clientName variable, strsplit() the client name, and use the second index of the split string in the filename.
eg. if I change clientName <- "myclient BBB", the output file would be Process_BBB.pdf.
I've tried changing the knit hook in the YAML header (example below), but I get errors because the clientName hasn't yet been defined.
title: "Process"
author: '***'
date: "`r format(Sys.time(), '%B %Y')`"
output:
pdf_document:
template: "/path/to/template.tex"
keep_tex: true
latex_engine: xelatex
knit: (function(inputFile, encoding) {
rmarkdown::render(inputFile,
encoding=encoding,
output_file= "`r paste0(
'Process_',
strsplit(clientName, ' ')[[1]][2],
'.pdf'
)`"
) })
When I move the knit hook to a portion of the .Rmd file after the clientName is defined, the output filename doesn't change.
I've also thought about creating a separate .R script with a function to render the document, but I need to reference the client name that's set in the .Rmd file; I haven't been able to source() a variable in that script from the .Rmd file...
Open to any suggestions

Comment control from YAML in R Markdown

I'm trying to control a comment from my YAML header with a parameter, but I can't seem to make it work.
Here is an example of my code.
---
title: My report
date: "`r format(Sys.time(), '%d %B, %Y')`"
output:
html_document: default
pdf_document: default
word_document: default
params:
optional_text: "TRUE"
---
`r if(optional_text){"My text"}`
I have tried a few things (with/without quotation marks, etc.), but I always end up with the same error
Error in eval(parse_only(code[i]), envir = envir) :
object 'optional_text' not found
I have figured out a walkaround in the meanwhile, but it just doesn't seem efficient.
```{r label, include=FALSE}
optional_text<-TRUE
```
You just have to change one little thing:
`r if(params$optional_text){"My text"}`
In RMD the parameters are called with params$NAME_OF_PARAMETER, see here: http://rmarkdown.rstudio.com/developer_parameterized_reports.html

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))

Using a YAML header argument in knitr

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)))) })
---

Rmarkdown: different output folders, shared libs

I have an .R file wherein I for each unique value in a list, render a number of different .Rmd files. Something like this:
for (uddannelse in unique(c("Monkey","Horse"))) {
rmarkdown::render("file1.Rmd", output_dir=file.path(getwd(), uddannelse) ,output_file=paste("file1", uddannelse,".html", sep="_"), encoding="UTF-8")
rmarkdown::render("file2.Rmd", output_dir=file.path(getwd(), uddannelse), output_file=paste("file2", uddannelse,".html", sep="_"), encoding="UTF-8")
}
As evident by the render parameters, the html-output should go into a separate folder for each value in the list, in the above example: folder: "Monkey" and folder "Horse".
Each .Rmd file has the following front matter (the files go to a static html website and needs to have self_contained: false:
---
output:
html_document:
theme: readable
self_contained: false
lib_dir: pub/libs
css: pub/libs/custom_css/custom.css
date: "`r format(Sys.time(), '%d %B, %Y')`"
---
However: When I call the render functions I recieve this error:
Error in relativeTo(basepath, dir) :
The path C:/Users/ac/Dropbox/2014_07_WIP/pub/libs/jquery-1.11.0 does not appear to be a descendant of C:/Users/ac/Dropbox/2014_07_WIP/Monkey/
So I guess the rmarkdwown::render first creates the lib directories relative to the Rmd file, yet expect the files to be placed relative to the output files.
How can I get around this, so that I can have a set of common Rmd input files in one folder, and have output in different folders, yet share a common lib?
I tried to place something like this in the fronmatter.
---
output:
html_document:
theme: readable
self_contained: false
lib_dir: "`r file.path(uddannelse, "libs")`"
css: "`r file.path(uddannelse, "libs", "custom_css", "custom.css")`"
date: "`r format(Sys.time(), '%d %B, %Y')`"
---
And I got this error:
Error in yaml::yaml.load(front_matter) :
Parser error: while parsing a block mapping at line 3, column 5did not find expected key at line 5, column 50
I solved my immediate problem by passing some of the front matter in the render call:
rmarkdown::render("file1.Rmd",
output_dir=file.path(uddannelse),
output_file=paste("file1", uddannelse,".html", sep="_"),
output_options=list(html_document =
list(self_contained = FALSE,
lib_dir = file.path(uddannelse, "lib"),
css = paste("lib", "custom_css", "custom.css",
sep="/"),
include = list(
after_body = file.path(uddannelse,
"footer_w_index.html")))),
encoding="UTF-8")
Notice that lib_dir has to be relative to the Rmdfile and css has to be relative to the output-file.
For some reason - regardless of whether I use paste or file.path(fsep="/", ...) the css path in the output file is linked with windows separator ("\") - and thus not usable in e.g. Firefox.

Resources