I'm trying to use RMarkdown to write posts about R for my blog (that uses Jekyll). Quite smooth except for one minor annoyance: I can't find a way to specify the output file inside the .Rmd document. By default, the output has the same name as the original document, only with a .md extension. I don't want to use the same name for both files because I follow the Jekyll convention of prefixing the .md files with the date, something that's not always necessary for the .Rmds.
I tried using the output_file argument on the front matter, but it didn't work. My hope is that there's a subtle way of passing parameters to rmarkdown::render from inside the document.
Here's a sample YAML front matter (does not work):
---
output:
md_document:
output_file: "2017-05-19-computacao-simbolica-R-2-4.md"
variant: markdown_github
html_document: null
---
Related
I am trying to put the references as bib tex with b-9.bib and with some styling with .csl files. Both the Rmarkdown and the aforementioned files are present in the same working directory. But I am encountering this error when trying to knit to PDF.
YAML Header
---
title: "Swarm Intelligence"
output: html_document
bibliography: b-9.bib
csl: ieee.csl
---
Not sure if it is because of the hyphenated naming or path issue. I even tried giving the absolute path to the header path but still the issue. or am I missing some extra code chunk or so?
Ensure all your files have the same working directory. Also, try using "word_document" as the output format. I am not sure how your csl formatting would apply to a html document.
I'm having some trouble to compile an entire document from many Rmd files by using the bookdown approach.
If I knit individual .Rmd files then 'preamble.tex' included in YAML options is taken into account.
If I render the book (with both approaches described here), then 'preamble.tex' is ignored.
To make things concrete, consider the following mwe:
preamble.tex:
\usepackage{times}
index.Rmd:
---
title: "My paper"
site: "bookdown::bookdown_site"
output:
bookdown::pdf_document2:
includes:
in_header: "preamble.tex"
---
01-intro.Rmd:
# Introduction
This chapter is an overview of the methods that we propose to solve an **important problem**.
Then, by knitting 'index.Rmd' or '01-intro.Rmd' the font indicated in 'preamble.tex' is used.
However when rendering with bookdown::render_book('index.Rmd',"bookdown::pdf_book", new_session = T) it is simply ignored.
What is more, in my actual project there are other output options that end up ignored. For example, I use toc: false and it works when knitting single files, but fails when rendering the document.
In this simple example it would be okay to use a single file, but my actual project has many chapters with R chunks within each of them. Thus, building a single file doesn't seem a good idea.
I appreciate any hints on what I am missing here.
Thanks in advance.
What you are missing here is that in your YAML header, preamble.tex is included for the bookdown::pdf_document2 output format and not bookdown::pdf_book, the format you pass to the output_format argument in bookdown::render_book(). For this reason, other YAML options (like toc: true) do not work either.
Running
bookdown::render_book('index.Rmd', "bookdown::pdf_document2", new_session = T)
instead should work.
I’m building a beamer-presentation template, and I would like to include a logo on the front of the slides. Although this could be achieved by including an image in the directory of the presentation, I would prefer not to have to create a new directory for each new presentation just for that one image.
Is there a way where I can retrieve the relative file path from within the package resources folder and have it reference that location in the LaTeX beamer template?
I have tried placing the image in the resources folder along with the .tex template but when I try to knit it I get a file not found error.
I managed to do this with kind of a workaround:
I derive the absolute path of the resource folder in the yaml header with an R function:
---
output:
myPackage::myCustomFunction
resource-folder: '`r system.file("rmarkdown/templates/myPackage/resources/", package="myPackage")`'
---
Inside my tex tamplate I use:
\includegraphics[]{$resource-folder$myImage.png}
This way I can place my images in the resource folder along with the tex template and don't have to copy them along with each new instance of the document.
This question has two key problems:
Have an easy way to provide a file path to an image, regardless of where the R Markdown file is.
Make it so that the logo does not have to be specified in the YAML each time, as seen in the solution by nnn
Overall solution
As this problem requires a package to be properly resolved, I have put together a really basic repository here, which you may want to fork. Alternatively you can download it here:
devtools::install_github("mikey-harper/rmarkdown-image")
Custom Function
It is useful to create your own R Markdown output for two reasons:
You can link to system files really easily. In this case, you want to have a reference to your logo.
You can provide default pandoc arguments, rather than having them in the YAML.
These two points can be used in tandem to provide the logo file (which is stored in the package) directly to the template titlegraphic YAML option. Here is the basic function from the package.
beamer_custom <- function(...){
# Define filepaths
logo <- system.file(package = "template", "logo.png")
template <- system.file(package = "template", "template.tex")
# supply files to your custom format
rmarkdown::beamer_presentation(...,
template = template,
pandoc_args = rmarkdown::pandoc_variable_arg("titlegraphic", logo))
}
Note that the ... in the function means that we can supply any arguments to our new function which will be passed directly to the beamer_presentation function.
Custom Template
Defining your own template isn't entirely necessary here, as the default template includes a lot of customisation options for beamer. I only made a single change to the template, and this was to force the logo size to be 2cm tall. I therefore added [height=2cm] to line 338:
\titlegraphic{\includegraphics[height=2cm]{$titlegraphic$}}
Using this in a template. Some additional options have been added to the output (theme, colortheme, fonttheme) to highlight that it is still easy to pass other arguments to our new function.
---
title: "R Markdown"
date: \today
author: Michael Harper
subtitle: How to make awesome R Markdown presentation
output:
template::beamer_custom:
theme: "AnnArbor"
colortheme: "dolphin"
fonttheme: "structurebold"
---
# Text
Beautiful text
You probably want to read Chapters 17 and 18 of the R Markdown book if the concept of making Custom formats sounds intimidating!
Is it possible to have multiple sets of shared options for R Markdown?
This is my problem: I have a folder with a bunch of markdown files. The files can be divided into two groups:
html_document and
revealjs::revealjs_presentation.
I would like to factor out common YAML code from each of these groups. Now I know that I can create a _output.yaml file which would capture common YAML, but I essentially need to have two of these files, one for each of the output formats.
I saw the use of pandoc_args suggested here and I gave it a try as follows:
---
title: Document Type 1
output:
html_document:
pandoc_args: './common-html.yaml'
---
and
---
title: Document Type 2
output:
revealjs::revealjs_presentation:
pandoc_args: './common-reveal.yaml'
---
However using this setup the options from the included YAML files don't get processed.
Any other suggestions would be appreciated!
You can specify multiple output formats in the same _output.yaml file like this (just some example options):
html_document:
self_contained: false
revealjs::revealjs_presentation:
incremental: true
Then you have to render all output formats which cannot be done directly using the RStudio GUI. Instead you have to enter the following into the R console:
rmarkdown::render(input = "your.Rmd",
output_format = "all")
Ideally make sure that there's no output key in the YAML front matter of the .Rmd document itself. Otherwise the output options in _output.yaml file might get overridden. Unfortunately I couldn't find a comprehensive documentation of the exact behavior. Some of my observations so far:
Output options defined in the YAML front matter of the .Rmd document itself always override those specified in the shared options file _output.yaml.
Specifying an output format using the default option set (like pdf_document: default) in the YAML front matter of the .Rmd document itself completely overrides all options specified in _output.yaml. But if you don't explicitly specify the default options (like output: pdf_document; which is only possible for a single output format at once), the _output.yaml content is fully regarded.
If you have specified options for multiple output formats in _output.yaml, only the first one gets rendered when pressing the knit button in RStudio (even if you explicitly press knit to HTML/PDF/Word). You have to use rmarkdown::render(output_format = "all") to render the other formats, too.
I have a few Rmd documents that all have the same YAML frontmatter except for the title. How can I keep this frontmatter in one file and have it used for all the documents? It is getting rather large and I don't want to keep every file in step every time I tweak the frontmatter.
I want to still
use the Knit button/Ctrl+Shift+K shortcut in RStudio to do the compile
keep the whole setup portable: would like to avoid writing a custom output format or overriding rstudio.markdownToHTML (as this would require me to carry around a .Rprofile too)
Example
common.yaml:
author: me
date: "`r format (Sys.time(), format='%Y-%m-%d %H:%M:%S %z')`"
link-citations: true
reference-section-title: References
# many other options
an example document
----
title: On the Culinary Preferences of Anthropomorphic Cats
----
I do not like green eggs and ham. I do not like them, Sam I Am!
Desired output:
The compiled example document (ie either HTML or PDF), which has been compiled with the metadata in common.yaml injected in. The R code in the YAML (in this case, the date) would be compiled as a bonus, but it is not necessary (I only use it for the date which I don't really need).
Options/Solutions?
I haven't quite got any of these working yet.
With rmarkdown one can create a _output.yaml to put common YAML metadata, but this will put all of that metadata under output: in the YAML so is only good for options under html_document: and pdf_document:, and not for things like author, date, ...
write a knitr chunk to import the YAML, e.g.
----
title: On the Culinary Preferences of Anthropomorphic Cats
```{r echo=F, results='asis'}
cat(readLines('common.yaml'), sep='\n')
```
----
I do not like green eggs and ham. I do not like them, Sam I Am!
This works if I knitr('input.Rmd') and then pandoc the output, but not if I use the Knit button from Rstudio (which I assume calls render), because this parses the metadata first before running knitr, and the metadata is malformed until knitr has been run.
Makefile: if I was clever enough I could write a Makefile or something to inject common.yaml into input.Rmd, then run rmarkdown::render(), and somehow hook it up to the Knit button of Rstudio, and perhaps somehow save this Rstudio configuration into the .Rproj file so that the whole thing is portable without me needing to edit .Rprofile too. But I'm not clever enough.
EDIT: I had a go at this last option and hooked up a Makefile to the Build command (Ctrl+Shift+B). However, this will build the same target every time I use it via Ctrl+Shift+B, and I want to build the target that corresponds with the Rmd file I currently have open in the editor [as for Ctrl+Shift+K].
Have found two options to do this portably (ie no .Rprofile customisation needed, minimal duplication of YAML frontmatter):
You can provide common yaml to pandoc on the command-line! d'oh!
You can set the knit: property of the metadata to your own function to have greater control over what happens when you Ctrl+Shift+K.
Option 1: common YAML to command line.
Put all the common YAML in its own file
common.yaml:
---
author: me
date: "`r format (Sys.time(), format='%Y-%m-%d %H:%M:%S %z')`"
link-citations: true
reference-section-title: References
---
Note it's complete, ie the --- are needed.
Then in the document you can specify the YAML as the last argument to pandoc, and it'll apply the YAML (see this github issue)
in example.rmd:
---
title: On the Culinary Preferences of Anthropomorphic Cats
output:
html_document:
pandoc_args: './common.yaml'
---
I do not like green eggs and ham. I do not like them, Sam I Am!
You could even put the html_document: stuff in an _output.yaml since rmarkdown will take that and place it under output: for all the documents in that folder. In this way there can be no duplication of YAML between all documents using this frontmatter.
Pros:
no duplication of YAML frontmatter.
very clean
Cons:
the common YAML is not passed through knit, so the date field above will not be parsed. You will get the literal string "r format(Sys.time(), format='%Y-%m-%d %H:%M:%S %z')" as your date.
from the same github issue:
Metadata definitions seen first are kept and left unchanged, even if conflicting data is parsed at a later point.
Perhaps this could be a problem at some point depending on your setup.
Option 2: override the knit command
This allows for much greater control, though is a bit more cumbersome/tricky.
This link and this one mention an undocumented feature in rmarkdown: the knit: part of the YAML will be executed when one clicks the "Knit" button of Rstudio.
In short:
define a function myknit(inputFile, encoding) that would read the YAML, put it in to the RMD and call render on the result. Saved in its own file myknit.r.
in the YAML of example.rmd, add
knit: (function (...) { source('myknit.r'); myknit(...) })
It seems to have to be on one line. The reason for source('myknit.r') instead of just putting the function definition int he YAML is for portability. If I modify myknit.r I don't have to modify every document's YAML. This way, the only common YAML that all documents must repeat in their frontmatter is the knit line; all other common YAML can stay in common.yaml.
Then Ctrl+Shift+K works as I would hope from within Rstudio.
Further notes:
myknit could just be a system call to make if I had a makefile setup.
the injected YAML will be passed through rmarkdown and hence knitted, since it is injected before the call to render.
Preview window: so long as myknit produces a (single) message Output created: path/to/file.html, then the file will be shown in the preview window.
I have found that there can be only one such message in the output [not multiple], or you get no preview window. So if you use render (which makes an "Output created: basename.extension") message and the final produced file is actually elsewhere, you will need to suppress this message via either render(..., quiet=T) or suppressMessages(render(...)) (the former suppresses knitr progress and pandoc output too), and create your own message with the correct path.
Pros:
the YAML frontmatter is knitted
much more control than option 1 if you need to do custom pre- / post-processing.
Cons:
a bit more effort than option 1
the knit: line must be duplicated in each document (though by source('./myknit.r') at least the function definition may be stored in one central location)
Here is the setup for posterity. For portability, you only need to carry around myknit.r and common.yaml. No .Rprofile or project-specific config needed.
example.rmd:
---
title: On the Culinary Preferences of Anthropomorphic Cats
knit: (function (...) { source('myknit.r'); myknit(...) })
---
I do not like green eggs and ham. I do not like them, Sam I Am!
common.yaml [for example]:
author: me
date: "`r format (Sys.time(), format='%Y-%m-%d %H:%M:%S %z')`"
link-citations: true
reference-section-title: References
myknit.r:
myknit <- function (inputFile, encoding, yaml='common.yaml') {
# read in the YAML + src file
yaml <- readLines(yaml)
rmd <- readLines(inputFile)
# insert the YAML in after the first ---
# I'm assuming all my RMDs have properly-formed YAML and that the first
# occurence of --- starts the YAML. You could do proper validation if you wanted.
yamlHeader <- grep('^---$', rmd)[1]
# put the yaml in
rmd <- append(rmd, yaml, after=yamlHeader)
# write out to a temp file
ofile <- file.path(tempdir(), basename(inputFile))
writeLines(rmd, ofile)
# render with rmarkdown.
message(ofile)
ofile <- rmarkdown::render(ofile, encoding=encoding, envir=new.env())
# copy back to the current directory.
file.copy(ofile, file.path(dirname(inputFile), basename(ofile)), overwrite=T)
}
Pressing Ctrl+Shift+K/Knit from the editor of example.rmd will compile the result and show a preview. I know it is using common.yaml, because the result includes the date and author whereas example.rmd on its own does not have a date or author.
The first solution proposed by #mathematical.coffee is a good approach, but the example it gave did not work for me (maybe because the syntax had changed). As said so, this is possible by providing pandoc arguments in the YAML header. For example,
It's the content of a header.yaml file:
title: "Crime and Punishment"
author: "Fyodor Dostoevsky"
Add this to the beginning of the RMarkdown file:
---
output:
html_document:
pandoc_args: ["--metadata-file=header.yaml"]
---
See the pandoc manual for the --metadata-file argument.