I have been using this solution to generate r-markdown reports from an interactive (Shiny) app.
Rather than generate and download a html file, I'm looking generate the corresponding .rmd file, since I want to be able to rerun the report with fixed settings at a later point in time.
To provide an example, using the template provided in the link, and for n=40, I want to generate a file containing the following code:
---
title: "Dynamic report"
output: html_document
params:
n: 40
---
```{r}
# The `params` object is available in the document.
params$n
```
In other words, a file in which the placeholder 'NA' from the template is replaced by the actual used value of 40.
Short of manipulating the yaml in the file directly, is there a way to set new parameters in a rmd template and generate the resulting .rmd file?
An extremely simple version to help with your parameters Rmarkdown question. This requires Rstudio. Instead of regularly knitting your document, you knit with parameters...
Now we get a GUI interface where we can specify the value we want, in this case we made it "numeric"
---
title: My Document
output: html_document
params:
input: numeric
---
`r params$input`
Which renders and includes our interactive parameter inside the Rmarkdown HTML rendered document. resources I used for research: resource 1 and resource 2. You can do wayy more with parameters, but this was a simple answer to help provide you with an answer to your question.
Related
I have a shiny application in which a user can enter information through a form with various inputs like text, date etc. Once entered, this information is stored in a table in the backend. Now on the basis of this, the user wants to generate a document/pdf in a particular format for printing. Here is a demo of what the final filled up form might look like:
All the fields, for example, the billed to address, payment method, shipped to etc. are entered through the form and are stored in a table. How do I extract this information from a table and show it in this format? I am looking at parameterized Rmarkdown documents, but don't know how to get the format correct.
As for getting parameters into an rmarkdown file, you can use the yaml header. Since your data is most likely coming from a reactive environment, you have to save the object to the global environment using the <<- operator or assign(). These values can then be accessed from the Rmarkdown file with the yaml header. Say you have created an object called address:
---
output: pdf_document
address: NA
---
As of the formatting the report, you will need to use latex code, either inside the Rmarkdown document and/or you specify a .tex file in the yaml header:
---
output:
pdf_document:
includes:
in_header: preamble.tex
address: NA
---
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.
When using knitr and rmarkdown together to create a word document you can use an existing document to style the output.
For example in my yaml header:
output:
word_document:
reference_docx: style.docx
fig_caption: TRUE
within this style i have created a default table style - the goal here is to have the kable table output in the correct style.
When I knit the word document and use the style.docx the tables are not stylized according to the table.
Using the style inspector has not been helpful so far, unsure if the default table style is the incorrect style to modify.
Example Code:
```{r kable}
n <- 100
x <- rnorm(n)
y <- 2*x + rnorm(n)
out <- lm(y ~ x)
library(knitr)
kable(summary(out)$coef, digits=2, caption = "Test Captions")
```
I do not have a stylized document I can upload for testing unfortunately.
TL;DR: Want to stylise table output from rmarkdown and knitr automatically (via kable)
Update: So far I have found that changing the 'compact' style in the docx will alter the text contents of the table automatically - but this does not address the overall table styling such as cell colour and alignment.
Update 2: After more research and creation of styles I found that knitr seems to have no problem accessing paragraph styles. However table styles are not under that style category and don't seem to apply in my personal testing.
Update 3: Dabbled with the ReporteRs package - whilst it was able to produce the tables as a desired the syntax required to do so is laborious. Much rather the style be automatically applied.
Update 4: You cannot change TableNormal style, nor does setting a Table Normal style work. The XML approach is not what we are looking for. I have a VBA macro that will do the trick, just want to remove that process if possible.
This is essentially a combination of the answer that recommends TableNormal, this post on rmarkdown.rstudio.com and my own experiments to show how to use a TableNormal style to customize tables like those generated by kable:
RMD:
---
output:
word_document
---
```{r}
knitr::kable(cars)
```
Click "Knit Word" in RStudio. → The document opens in Word, without any custom styles yet.
In that document (not in a new document), add the required styles. This article explains the basics. Key is not to apply direct styles but to modify the styles. See this article on support.office.com on Style basics in Word.
Specifically, to style a table you need to add a table style. My version of Word is non-English, but according to the article linked above table styles are available via "the Design tab, on the Table Tools contextual tab".
Choose TableNormal as style name and define the desired styles. In my experiments most styles worked, however some did not. (Adding a color to the first column and making the first row bold was no problem; highlighting every second row was ignored.) The last screenshot in this answer illustrates this step.
Save the document, e.g. as styles.docx.
Modify the header in the RMD file to use the reference DOCX (see here; don't screw up the indentation – took me 10 minutes find this mistake):
---
output:
word_document:
reference_docx: styles.docx
---
Knit to DOCX again – the style should now be applied.
Following the steps I described above yields this output:
And here a screenshot of the table style dialog used to define TableNormal. Unfortunately it is in German, but maybe someone can provide an English version of it:
As this does not seem to work for most users (anyone but me …), I suggest we test this systematically. Essentially, there are 4 steps that can go wrong:
Wrong RMD (unlikely).
Differences in the initially generated DOCX.
Differences in how the TableNormal style is saved in the DOCX.
Differences in how the reference DOCX is used to format the final DOCX.
I therefore suggest using the same minimal RMD posted above (full code on pastebin) to find out where the results start do differ:
My initially generated DOCX.
The same document with TableNormal added: reference.docx
The final document.
The three files are generated on the following system: Windows 7 / R 3.3.0 / RStudio 0.99.896 / pandoc 1.15.2 / Office 2010.
I get the same results on a system with Windows 7 / R 3.2.4 / RStudio 0.99.484 / pandoc 1.13.1 / Office 2010.
I suppose the most likely culprits are the pandoc and the Office versions. Unfortunately, I cannot test other configurations at the moment. Now it would be interesting to see the following: For users where it does not work, what happens …
… if you start from my initial.docx?
If that does not work, what if you use my reference.docx as reference document?
If nothing works, are there eye-catching differences in the generated XML files (inside the DOCX container)? Please share your files and exact version information.
With a number of users running these tests it should be possible to find out what is causing the problems.
This was actually a known issue. Fortunately, it was solved in v2.0 or later releases of pandoc.
And I have tested the newer version, and found that there is a newly-added hidden style called "Table". Following #CL.'s suggestions to change "Table" style in reference.docx will be okay now.
In addition, look at this entry of pandoc's v2.0 release notes:
Use Table rather than Table Normal for table style (#3275). Table Normal is the default table style and can’t be modified.
As of 2021, I could not get any of the other suggested answers to work.
However, I did discover the {officedown} package, which, amongst other things, supports the styling of tables in .docx documents. You can install {officedown} with remotes::install_github("davidgohel/officedown")
To use {officedown} to render .Rmd to .docx you must replace
output:
word_document
in your document header with
output:
officedown::rdocx_document
In addition to this the {officedown} package must be loaded in your .Rmd.
As with the word_document output format, {officedown} allows us to use styles and settings from template documents, again with the reference_docx parameter.
With a reference document styles.docx, a minimal example .Rmd may look like:
---
date: "2038-01-19"
author: "The Reasonabilists"
title: "The end of time as we know it"
output:
officedown::rdocx_document:
reference_docx: styles.docx
---
```{r setup, include = FALSE}
# Don't forget about me: I'm important!
library("officedown")
```
{officedown} allows us to go one step further and specify the name of the table style to use in the document's front matter. This table style could be a custom style we created in styles.docx, or it could be one of Word's in-built styles you prefer.
Let's say we created a style My Table:
We could tell {officedown} to use this table style in our front matter as:
output:
officedown::rdocx_document:
reference_docx: styles.docx
tables:
style: My Table
Putting this altogether, knitting the minimal .Rmd:
---
date: "2038-01-19"
author: "The Reasonabilists"
title: "The end of time as we know it"
output:
officedown::rdocx_document:
reference_docx: styles.docx
tables:
style: My Table
---
```{r setup, include = FALSE}
# Don't forget about me: I'm important!
library(officedown)
```
```{r}
head(mtcars)
```
Resulting in a .docx document which looks like:
TableNormal doesn't work for me too.
On my Dutch version of Word 2016 (Office 365), I found out that I could markup tables with the style Compact.
Input (refdoc.docx contains the Compact style):
---
title: "Titel"
subtitle: "Ondertitel"
author: "`r Sys.getenv('USERNAME')`"
output:
word_document:
toc: true
toc_depth: 2
fig_width: 6.5
fig_height: 3.5
fig_caption: true
reference_docx: "refdoc.docx"
---
And RMarkdown:
# Methoden {#methoden}
```{r}
kable(cars)
```
Output:
You need to have a reference_docx: style.docx which has "Table" style in it. (see #Liang Zhang's explanation and links above).
Create a basis reference document using pandoc (source). In command line (or cmd.exe on Windows) run:
pandoc -o custom-reference.docx --print-default-data-file reference.docx
In this newly created reference.docx file, find the table created (a basic 1 row table with a caption).
While the table is selected, click "Table Design" and find "Modify Table Style":
Modify the style of the table as you wish and use this reference document in your RMD document (see the first answer by #CL.).
Using this reference document, you can also change the table and figure caption styles.
I was able to get my word output to use a default table style that I defined in a reference .docx.
Instead of 'TableNormal', the table style it defaulted to was 'Table'.
I discovered this by knitting an rmarkdown with a kable.
---
date: "December 1, 2017"
output:
word_document:
reference_docx: Template.docx
---
`r knitr::kable(source)`
Then I took a look at that generated document's XML to see what style it had defaulted to.
require(XML)
docx.file <- "generated_doc.docx"
## unzip the docx converted by Pandoc
system(paste("unzip", docx.file, "-d temp_dir"))
document.xml <- "temp_dir/word/document.xml"
doc <- xmlParse(document.xml)
tblStyle <- getNodeSet(xmlRoot(doc), "//w:tblStyle")
tblStyle
I defined the 'Table' style to put some color and borders in the reference docx. This works for one standard table style throughout the document, I haven't found a way to use different styles throughout.
This stayed true even after I opened the reference doc and edited it.
In short: Is there a way to manipulate RMarkdown's metadata-list generated from the YAML header from within the following R-code chunks? To illustrate, I've tried the following:
---
title: "Untitled"
output: html_document
---
```{r}
rmarkdown::metadata$title <- "New title"
rmarkdown::metadata$title
```
This throws an error, though.
Error in rmarkdown::metadata$title <- "New title" :
Object 'rmarkdown' not found
Background
I'm working on a RMarkdown TeX-template. Some parts of the preamble need to be localized depending on the variable lang defined in the YAML header. My current approach is to check the value of metadata$lang and create a list of corresponding terms. I wanted to add the contents of the list to metadata and access the terms in the TeX-template via $loc_wordcount$, for example.
I think that the answer to this is no (though, I'm not 100% sure of that).
But, there is a different way to do it. You can use a parameterized report (https://bookdown.org/yihui/rmarkdown-cookbook/parameterized-reports.html).
The way to do that would be:
Create an rmarkdown file (e.g. called "input.Rmd") with parameters named param$value:
---
title: "params$new_title"
output: html_document
---
The rest of the report goes here.
Then render the report with a parameter passed in:
rmarkdown::render('input.Rmd', params = list(new_title = "New title"))