R RMarkDown knit_expand encoding - r

In file main.rmd have the follownig code:
```{r, include=FALSE}
out = NULL
for (i in vector) {
out = c(out, knit_expand("file2.rmd"))
}
```
`r paste(knit(text = out), collapse = '\n')`
Both files are saved using UTF-8. However, local signs from file2.rmd are not displayed correctly, whereas content from main.rmd is displayed without any problem. Adding encoding="UTF-8" to knit function does not solve the problem. How can I fix it?

You may change
knit_expand("file2.rmd")
to
knit_expand(text = readLines("file2.rmd", encoding = "UTF-8"))

Related

Highlighting some references in RMarkdown documents?

Is it possible to emphasise (e.g., put in bold) some references that contain a particular string (e.g., the name of a particular author) in a papaja .Rmd document (where the refs are taken from a bib file and using the apa7.csl file)?
I can propose this solution based on pandoc lua filter which would work for not just pdf but also html output and doesn't require manual editing of latex or html file.
---
title: "The title"
bibliography: "r-references.bib"
output:
pdf_document:
pandoc_args: [ "--lua-filter", "ref-bold.lua"]
html_document:
pandoc_args: [ "--lua-filter", "ref-bold.lua"]
---
```{r setup, include = FALSE}
library("papaja")
r_refs("r-references.bib")
```
We used `R` [#R-base] and `Tidyverse` [#R-tidyverse] for all our analyses. Especially [#R-tidyverse] made things easy.
\vspace{10mm}
# References
ref-bold.lua
function Cite(el)
if pandoc.utils.stringify(el.content) == "[#R-tidyverse]" then
return (pandoc.Strong(el))
end
end
This demo bolds all of the reference to tidyverse package, if we would wanted to bold the reference to base-R, we would modify the second line in ref-bold.lua as pandoc.utils.stringify(el.content) == "[#R-base]" and all instances of references to base-R would be bold (highlighted).
pdf output
html output
A Lua-Filter would be the most elegant solution. If you use BibLaTeX and biber, you can use the general annotation feature (see this SO answer).
Include the following in your preamble:
\renewcommand*{\mkbibnamegiven}[1]{%
\ifitemannotation{bold}
{\textbf{#1}}
{#1}}
\renewcommand*{\mkbibnamefamily}[1]{%
\ifitemannotation{bold}
{\textbf{#1}}
{#1}}
In your bib-file, use the Author+an field to define which author to highlight:
#Misc{pawel2022power,
title = {Power Priors for Replication Studies},
author = {S Pawel and F Aust and L Held and E J Wagenmakers},
year = {2022},
eprinttype = {arxiv},
eprint = {2207.14720},
url = {https://arxiv.org/abs/2207.14720},
Author+an = {2=bold}
}
Now, render the R Markdown file with XeLaTeX, keep the intermediate files and the TeX file, and render the TeX file again using biber:
rmarkdown::render("paper.Rmd", clean = FALSE)
tinytex::xelatex("academic.tex", bib_engine = "biber")
Posting a solution in case it can be useful to others as well. We can first render the LaTeX file from the RMarkdown document, then find and replace all instances of the name to be emphasised, and finally generate the pdf from the modified LaTeX file.
# knitting the original Rmd file (with "keep_tex: true" in YAML)
rmarkdown::render(input = "some_file.Rmd")
# reading the generated LaTeX file
tex_file <- readLines(con = "some_file.tex")
# putting a particular author in bold in the references list
new_tex_file <- gsub(pattern = "James, W.", replace = "\\textbf{James, W.}", x = tex_file, fixed = TRUE)
# writing the (updated) LaTeX file
writeLines(text = new_tex_file, con = "some_file.tex")
# generating the pdf file (may need to be ran twice)
system(command = "xelatex some_file.tex")

R Markdown - Hyperlink outside Rmd file

I am wondering how we can define a hyperlink for R markdown outside Rmd file. Defining a hyperlink inside Rmd file is as easy as typing [hyperlink lable](actual link); but, if on the Rmd file, I am calling some other r-file (e.g., a function) that generates an address to a file, is there a way to transfer this information back to Rmd file to generate a hyperlink there?
Please see example below for more clarification:
Inside Rmd file:
myFun( with some input)
Inside myFun:
myFun <- function( with some input)
some calculations...
return("[click here](C:/myFile.docx)")
The output on the generated html page is:
[1] "[click here] (C:/myFile.docx)"
Which is not a hyperlink!
To define the links outside the rmd file you can use a parameterized report. This allows you to pass values into the rmarkdown document when you compile it. To do this, first create an rmarkdown document that includes the desired parameters, which are declared in the yaml header and then used later in the report. Then, in a separate R script, run the render command (from the rmarkdown package) and pass the desired parameter values.
Here's an example that uses cat or paste to generate the links. For comparison, I've also added a second set of parameters that add different links using the methods in #JohnCoene's answer. I've saved the rmarkdown document as "test.rmd", which is how the document is identified in the render command.
rmarkdown document
---
output: html_document
params:
text1: "add text"
link1: "add URL"
text2: "add text"
link2: "add URL"
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
```{r}
# Function to add link
myFun <- function(text, link, inline=TRUE) {
if(inline) {
paste("[", text, "](", link, ")", sep="")
} else {
cat("[", text, "](", link, ")", sep="")
}
}
```
Blah, blah, blah, more text. And here's the link:
```{r, results="asis"}
myFun(params$text1, params$link1, inline=FALSE)
```
Blah, blah, blah, more text. And here's a way to `r myFun(params$text1, params$link1)`.
Or, using the examples from `#JohnCoene's` answer:
With an HTML tag:
```{r, results="asis"}
tg <- function (link, text){
paste0("<a href='", link, "'>", text, "</a>")
}
tg(params$link2, params$text2)
```
With `htmltools`:
```{r}
# install.packages("htmltools")
library(htmltools)
tags$a(
href = params$link2,
params$text2
)
```
Separate R script to render the rmarkdown document
library(rmarkdown)
render(input="test.rmd",
params=list(text1="link to Stackoverflow",
link1="https://stackoverflow.com/questions/52745926/r-markdown-hyperlink-outside-rmd-file",
text2="link to google",
link2="https://google.com"))
Here's what the output html document looks like:
There are multiple solutions, return an html tag or use the htmltools package.
HTML tag
```{r, results="asis"}
tg <- function (link, text){
paste0("<a href='", link"'>", text, "</a>")
}
tg("http://google.com", "link to Google")
```
htmltools
Definitely recommend this way over the other.
```{r}
# install.packages("htmltools")
library(htmltools)
tags$a(
href = "https://google.com",
"Link to Google"
)
```
As mentioned in the question, assuming the output of 'myFun' function is the hyperlink string, here is what worked best for me:
Inside myFun:
myFun <- function()
...some calculations to generate a csv file...
return("C:/myFile.csv")
Inside Rmd file:
```{r, echo=FALSE}
myHyperlink <- myFun()
hyperlink_exists = !is.null(myHyperlink)
```
```{r, eval=hyperlink_exists, results="asis", echo=FALSE}
cat(paste0("The file is saved ","[", "Here", "](", myHyperlink, ")","\n"))
```

wrapping figure with latex environment in knitr/rmarkdown with hooks

I'd like to wrap figures created with knitr and rmarkdown in a "wrapfigure" environment using hooks. However, when running the minimal example below, the figure chunk only gets compiled into a markdown picture:
\begin{wrapfigure}{R}{0.3\textwidth}
![](test_files/figure-latex/unnamed-chunk-2-1.pdf)
\end{wrapfigure}
and not the expected:
\begin{wrapfigure}{R}{0.3\textwidth}
\includegraphics{test_files/figure-latex/unnamed-chunk-2-1.pdf}
\end{wrapfigure}
Minimal example:
---
header-includes:
- \usepackage{wrapfig}
output:
pdf_document:
keep_tex: TRUE
---
```{r}
library(knitr)
knit_hooks$set(wrapf = function(before, options, envir) {
if(before) {
"\\begin{wrapfigure}{R}{0.3\\textwidth}"
} else {
"\\end{wrapfigure}"
}
})
```
```{r, wrapf=TRUE}
library(ggplot2)
qplot(cars$speed, cars$dist)
```
pandoc is responsible for converting the markdown document to a TEX document. As pandoc doesn't touch between \begin{…} and \end{…} the markdown syntax for the image is not being converted to TEX syntax.
You could …
Hide the plot (fig.show = 'hide') and use something along the lines of cat("\includegraphics{figure/unnamed-chunk-2-1.pdf}").
Hide the plot as above and include some magic in the hook that saves the cat.
Write RNW instead of RMD if you want PDF output.
Here's an example for option 2:
knit_hooks$set(wrapf = function(before, options, envir) {
if(before) {
return("\\begin{wrapfigure}{R}{0.3\\textwidth}")
} else {
output <- vector(mode = "character", length = options$fig.num + 1)
for (i in 1:options$fig.num) {
output[i] <- sprintf("\\includegraphics{%s}", fig_path(number = i))
}
output[i+1] <- "\\end{wrapfigure}"
return(paste(output, collapse = ""))
}
})
This hook can be used with wrapf = TRUE and fig.show = "hide". (Moreover, you need to add \usepackage{graphics} to header-includes.)
But note that I would not do it! Too many things can go wrong in more complex settings. Think of cache, captions, labels, cache (again!) …
Therefore, if it is really necessary to control the typesetting of the PDF, I recommend writing RNW (option 3).

set fig.cap to options$label

How can I programmatically set a figure caption in a knitr hook?
I'd like to set the figure caption, if not explicitly defined, to the chunk label. I've read the knitr docs on options, options, and hooks, and though I think I understand the mechanisms at play, I can't get it to work.
My use-case that perhaps justifies this behavior: my work-flow recently adapted to start my data and visualization exploration in Rmd files. I'll use chunks for cleaning, subsetting, etc, and then a sample chunk for each visualization. This is quick and dirty, meaning minimal markdown. When I look over the report (typically rendered into PDF), I'll look at a figure and want to go straight to the source for it. Though text before/after the figure can provide insight, due to LaTeX figure rules it is not a sure thing. Counting figure numbers is feasible, but not "easy" (and becomes problematic with many figures). Captions are always with the figure, so it'd be great if I can default to filling the caption with the chunk label. (Yes, it's a little lazy of me.)
The MWE is below.
The hook code ran just fine; the returned strings in the hook appeared correctly. However, the figure caption did not change. Exception: when there is a chunk with an undefined fig.cap, all subsequent chunks have their caption set to the first un-captioned chunk name; this doesn't surprise me due to the global nature of opts_chunk, so that's out.
I suspect it might be related to "output hooks" vice "chunk hooks," but this really is a per-chunk thing and I do not want to modify the plot, just set the caption.
MWE:
---
title: "Document Title"
author: "My Name"
output:
pdf_document:
fig_caption: yes
---
# Header
```{r setup}
knit_hooks$set(autocap = function(before, options, envir) {
if (before) {
if (is.null(options$fig.cap)) {
options$fig.cap <- options$label
knitr::opts_current$set(fig.cap = options$label)
knitr::opts_chunk$set(fig.cap = options$label) # wrong!
paste('Set: `', options$label, '`, `',
knitr::opts_current$get('fig.cap'), '`', sep = '')
} else {
paste('Kept: `', options$fig.cap, '`', sep = '')
}
}
})
opts_chunk$set(autocap = TRUE)
```
## No Plot
```{r textOnly}
1+1
```
## Caption Already Set
```{r someplot, fig.cap='someplot caption'}
plot(0)
```
## Caption Not Set
```{r anotherPlot}
plot(1)
```
Is it ok like this ? I simply modify the knitr internal function .img.cap function which can be found here.
```{r}
.img.cap = function(options) {
if(is.null(options$fig.cap)) options$label else options$fig.cap
}
assignInNamespace(".img.cap", .img.cap, ns="knitr")
```
Does it help ?
```{r}
library(knitr)
knit_hooks$set(htmlcap = function(before, options, envir) {
if(!before) {
caption <- ifelse(is.character(options$htmlcap), options$htmlcap, options$label)
paste('<p class="caption">', caption, "</p>", sep="")
}
})
```
```{r Hello, htmlcap=TRUE}
library(ggplot2)
ggplot(diamonds,aes(price,carat)) + geom_point()
```
```{r, htmlcap="Hello again"}
ggplot(diamonds,aes(price,carat)) + geom_point()
```

R markdown file: include help information

I would like to include at the end of the R markdown documention the help page about the mtcars dataset.
In my file I included the following:
```{r}
?mtcars
```
When I compile the markdown (output is to PDF - knitr), upon processing this instruction the help page comes up in my browser but the resulting pdf lacks this section.
Is there a way I could acheive this other then copying from one place to the other?
Thank you.
We can adapt Yihui Xie's static_help function to get the html source for a given help file
static_help <- function(pkg, topic, out, links = tools::findHTMLlinks()) {
pkgRdDB = tools:::fetchRdDB(file.path(find.package(pkg), 'help', pkg))
force(links)
tools::Rd2HTML(pkgRdDB[[topic]], out, package = pkg,
Links = links, no_links = is.null(links))
}
If we write the source to a temporary file we can then read it back in and strip off the header and footer, giving you the body of the help file to include in your markdown document
```{r, echo = FALSE, results = "asis"}
static_help <- function(pkg, topic, out, links = tools::findHTMLlinks()) {
pkgRdDB = tools:::fetchRdDB(file.path(find.package(pkg), 'help', pkg))
force(links)
tools::Rd2HTML(pkgRdDB[[topic]], out, package = pkg,
Links = links, no_links = is.null(links))
}
tmp <- tempfile()
static_help("datasets", "mtcars", tmp)
out <- readLines(tmp)
headfoot <- grep("body", out)
cat(out[(headfoot[1] + 1):(headfoot[2] - 1)], sep = "\n")
```
EDIT
The above solution produced HTML output, whereas the question actually asked for PDF output. We can adapt the above to return latex output instead; this time the only-post-editing required is to switch % for \n
```{r, echo = FALSE, results = "asis"}
static_help <- function(pkg, topic, out, links = tools::findHTMLlinks()) {
pkgRdDB = tools:::fetchRdDB(file.path(find.package(pkg), 'help', pkg))
force(links)
tools::Rd2latex(pkgRdDB[[topic]], out, package = pkg,
Links = links, no_links = is.null(links))
}
tmp <- tempfile()
static_help("datasets", "mtcars", tmp)
out <- readLines(tmp)
out <- gsub("%", "\n", out, fixed = TRUE)
cat(out, sep = "\n")
```
However the .Rd files depend on Rd.sty. The simplest way to get LaTeX to find Rd.sty is to put a copy in the same directory as your .Rmd file. Then you need to define a custom template to replace the default pandoc LaTeX template. Again, the simplest solution is to put a copy of the default template in the same directory as your .Rmd file, then modify it by replacing everything between the \documentclass command and the \begin{document} command (lines 2 - 145) with the command
\usepackage{Rd}
Finally modify the metadata of your .Rmd file to use the new template
---
output:
pdf_document:
template: template.tex
---

Resources