Special character (ampersand) inside LaTeX environment - r

I have a character vector containing ampersand (&) that displays correctly when used outside LaTeX environment, such as \begin{itemize}.
This works:
---
output:
pdf_document
---
`r "Guns & Roses"`
The above code runs without error, meaning that either knitr or rmarkdown escapes the ampersand automatically.
Now, when the same R character vector with ampersand is specified inside LaTeX environment, following error is thrown: ! Misplaced alignment tab character &.:
---
output:
pdf_document
---
\begin{itemize}
\item `r "Guns & Roses"`
\end{itemize}

The reason why the first snippet in the question runs without errors but the second does not is that the & needs to be escaped in LaTeX and pandoc escapes it in the first case but not in the second.
This is because pandoc (with the extension raw_tex) doesn't escape "material between the begin and end tags".
knitr's output hook inline can be used to solve the problem.
One solution—that works for the OP, according to the comments—is to enclose output from R inline expressions in a verbatim environment where the & characer is allowed.
---
output:
pdf_document
---
```{r, echo = FALSE}
knitr::knit_hooks$set(inline = function(x) {
return(paste("\\verb|", x, "|"))
})
```
\begin{itemize}
\item `r "Guns & Roses"`
\end{itemize}
Alternatively, the following output hook for inline expressions could be used to replace all & by \&:
knitr::knit_hooks$set(inline = function(x) {
return(gsub(pattern = "&",
replacement = "\\&",
x = x,
fixed = TRUE))
})

I had a similar problem in Rmarkdown, where the Ampersand was supposed to show up in the labels of a ggplot. Using the output hooks CL suggested did not work for me. However, what did help was to put this specific ggplot into its own code chunk (note that I did not escape the ampersand! It is only part of a string variable)– Perhaps a strange workaround for Rmarkdown hickups but seems to work.

Related

Remove colon in figure caption using pandoc and bookdown in R Markdown

I am changing the font of a figure caption in my R Markdown and am using bookdown and pandoc to do so. My question is closely related to: How to change the figure caption format in bookdown?. I was able to get correct figure numbering and was able to alter the format of the "Figure 1" portion of the caption. However, I cannot figure out how to remove the colon in the output (i.e., "Figure 1:. ").
Minimal Example
Pandoc Function (taken from here)
function Image (img)
img.caption[1] = pandoc.Strong(img.caption[1])
img.caption[3] = pandoc.Strong(img.caption[3])
img.caption[4] = pandoc.Strong(". ")
return img
end
To use function Image in the R Markdown, save the file as "figure_caption_patch.lua", which will be called in pandoc_args in the YAML metadata.
R Markdown
---
title: Hello World
author: "Somebody"
output:
bookdown::word_document2:
fig_caption: yes
number_sections: FALSE
pandoc_args: ["--lua-filter", "figure_caption_patch.lua"]
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
# Test
Some text (Figure \#ref(fig:Xray)). Some text followed by a figure:
```{r Xray, fig.cap="Single-crystal X-ray structure of some text", echo=FALSE}
plot(cars)
```
Output
Figure 1:. This is a caption.
Desired Output
Figure 1. This is a caption.
In the pandoc function, I tried to subset the string of img.caption[3], but it did not work. I tried the following:
img.caption[3] = pandoc.Strong(string.sub(img.caption[3], 1, 1))
I know that if I was using R, then I could do something like:
a = c("words", "again")
substring(a, 1, 1)[1]
#output
[1] "w"
But unsure, how to do this with pandoc.
Looks like there was a change in rmarkdown which adds a colon by default. Also the reason why the answer in the linked post does not work anymore. For more on this and a solution see https://community.rstudio.com/t/how-to-change-the-figure-table-caption-style-in-bookdown/110397.
Besides the solution offered there you could achieve your desired result by replacing the colon by a dot. Adapting the lua filter provided by https://stackoverflow.com/a/59301855/12993861 this could done like so:
function Image (img)
img.caption[1] = pandoc.Strong(img.caption[1])
img.caption[3] = pandoc.Strong(pandoc.Str(string.gsub(img.caption[3].text, ":", ".")))
return img
end

How can I make inline r script visible in RMarkdown report?

Suppose that the command isn't important enough to have it on the separate line, But I still want it to be visible along the result, I know there is ` r inlinestr` in R Markdown, but it I can't pass echo=T to it. I want the result to be something like this:
You could use backticks, which would give you the monospace font, but not the gray background shading:
f. There are `sum(is.na(df$Height)) =` `r sum(is.na(df$Height))` missing Height values.
I just ran across this question that I attempted to answer about two years ago and thought of a way to get both the code and its evaluated output in a single inline statement. We just need a helper function. Below is an example. The code is entered as a text string and the function returns both the code and the result of evaluating the code:
---
title: "RMarkdown teaching demo"
author: "whoever"
output: pdf_document
---
```{r}
fnc = function(expr) {
paste(expr, " = ", eval(parse(text=expr)))
}
# Add some missing values
iris$Sepal.Length[c(3,5,10)] = NA
```
f. There are `r fnc("sum(is.na(iris$Sepal.Length))")` missing height values.
Below is the output.
It works, but there are two issues. First, the code is not in monospace font. Second, the code is not highlighted with a gray background.
I thought that I could get monospace font with the latex \texttt{} tag.
```{r}
fnc = function(expr) {
paste("\\texttt{", expr, " = ", eval(parse(text=expr)), "}", sep="")
}
```
This appears to return the desired string when run interactively ("\\texttt{sum(is.na(iris$Sepal.Length)) = 3}"), but throws the following error when I try to knit the document:
! Extra }, or forgotten $.
<recently read> \egroup
l.163 ...texttt{sum(is.na(iris$Sepal.Length)) = 3}
I thought I could get highlighting with the \hl{} tag (which also requires \usepackage{color, soul} in the latex header):
```{r}
fnc = function(expr) {
paste("\\hl{", expr, " = ", eval(parse(text=expr)), "}", sep="")
}
```
However, once again, this throws an error:
! Argument of \SOUL#addmath has an extra }.
<inserted text>
\par
l.161 ...re \hl{sum(is.na(iris$Sepal.Length)) = 3}
Both texttt{} and \hl{} work without a problem when used with regular text inside an rmarkdown document.
So, I'm not sure how to get the monospace font or highlighted text, but at least this takes a step toward code + evaluated code from a single inline R statement. Hopefully, someone with more knowledge of computing on the language and outputting latex markup can provide more insight into how to get this to work as desired.

How to get \bm{} to work in an R markdown (to HTML) file?

My R Markdown (.Rmd) file looks like this:
---
title: Foo
author: Marius Hofert
header-includes:
- \usepackage{bm}
output:
pdf_document
vignette: >
%\VignetteEngine{knitr::rmarkdown}
%\VignetteIndexEntry{Foo}
---
\[
\begin{align}
\bm{U}=a\bm{X}\quad\boldmath{U}=a\boldmath{X}\quad\mathbf{U}=a\mathbf{X}.
\end{align}
\]
The output (obtained via R CMD build and the looking in ./inst/doc/*.html) is this:
For getting italics bold vectors, I would like to use \bm{X} in my .Rmd document, but it fails (although I load the package bm). Why? The same happens without the output: pdf_document part.
UPDATE
If I'm running
---
title: Foo
author: Marius Hofert
header-includes:
- \usepackage{bm}
output:
pdf_document
vignette: >
%\VignetteEngine{knitr::rmarkdown}
%\VignetteIndexEntry{Foo}
---
\[
\begin{align}
\bm{U}=a\bm{X}\quad\boldmath{U}=a\boldmath{X}\quad\mathbf{U}=a\mathbf{X}.
\end{align}
\]
\[
\bm{U}=a\bm{X}\quad\boldmath{U}=a\boldmath{X}\quad\mathbf{U}=a\mathbf{X}.
\]
\begin{align}
\bm{U}=a\bm{X}\quad\boldmath{U}=a\boldmath{X}\quad\mathbf{U}=a\mathbf{X}.
\end{align}
I get (without errors)
I don't think Mathjax (which is what Pandoc uses in HTML output) can \usepackage{}. I work around this by having 2 files: one called preamble-mathjax.tex, one called preamble-latex.texMy YAML metadata is set up like this (for rmarkdown):
output:
html_document:
includes:
before_body: preamble-mathjax.tex
pdf_document:
includes:
in_header: preamble-latex.tex
And preamble-mathjax.tex has (note surrounding \( \) so that mathjax parses as a maths block)
\(
\newcommand{\bm}[1]{\boldsymbol{\mathbf{#1}}}
\)
while preamble-latex.tex has:
\usepackage{bm}
So that whenever I use \bm{..} in my document, it works whether I compile to HTML or PDF. (stacking the boldsymbol with the mathbf so that both greek letters and normal letters are made bold, and bold letters remain upright as they would if you used \bm).
Peripheral to your question:
Eventually you may wish to have a third file, preamble-both.tex, with macros that are not package-specific (supposing the relevant preamble-* has already been included) e.g.
\newcommand{\bX}{\bm{X}} % bold X
\newcommand{\R}{\mathbb{R}} % real numbers
And then you include this with both output formats. This saves you from writing all your macros twice, once for html_document and again for pdf_document. However, MathJax requires the macros to be surrounded by \( and \), whereas LaTeX will error out if this is the case.
The only way I've found to work around this is to have a file bracket-start.txt containing just \( and a file bracket-end.txt containing just \), so that my YAML is:
output:
html_document:
includes:
before_body: [preamble-mathjax.tex, bracket-start.txt, preamble-both.tex, bracket-end.txt]
pdf_document:
includes:
in_header: preamble-latex.tex
before_body: preamble-both.tex
which is pretty unwieldy, but it works (there is the Pandoc latex_macros extension, but it has never worked for me)
I think your \[ \] and \begin{align} ... \end{align} are redundant. When I ran it as written above I got
! Package amsmath Error: Erroneous nesting of equation structures;
(amsmath) trying to recover with `aligned'.
See the amsmath package documentation for explanation.
Type H for immediate help.
...
l.84 \end{align}
Worked fine for me when I deleted \begin{align} ... \end{align} ...
(It seems that a similar issue arose in your previous question too ...)
(Perhaps you were getting errors that you didn't notice and were accidentally looking at a previously compiled version?)
As far as why you don't get the right HTML output: I'm pretty certain that MathJax (the engine used to render LaTeX embedded in Rmarkdown-produced HTML) doesn't know about \boldmath; adding the package to your LaTeX input won't help, you'll have to use \mathbf and \boldsymbol instead. You can play around here to see what works and what doesn't: entering
$\bm X \boldmath X \boldsymbol X \mathbf X$
at that web page gives
Bottom line, if you want fancy math rendered properly, you're probably better off sticking to PDF output.
Another solution is to use the child chunk argument. The downside, which is kind of major, is that it will only work for math surrounded by $ $ or $$ $$. It won't work in the equation environment. The upside is that you do not get your definitions "flashing" at the top of your html pages for a moment, which happens to me with the solution above.
demo.Rmd
---
title: Foo
output:
pdf_document: default
html_document: default
---
```{r child = 'defs.tex'}
```
My math definitions are in defs.tex. Now I can use the defs in equations
but they need to be in math mode for html output. This works for both
pdf and html:
$\AA^\top\BB$ and
$$\AA^\top\BB$$
But using your new commands in the equation environment
only works for pdf output because pandoc will not expand the
definitions if the newcommands are not in $ $ or $$ $$.
\begin{equation}
\AA^\top\BB
\end{equation}
defs.tex
\newcommand{\BB}{\mathbf{B}}
\newcommand{\CC}{\mathbf{C}}
\renewcommand{\AA}{\mathbf{A}}
A third solution works well if you are using Mathjax to render equations in your html docs. Mathjax is on by default in pandoc in RStudio. This has the advantage of no flickering and works in $$ $$ and the equation environment. The big downside to this is that pandoc strips \ref{} out of the html so you have to add a knit hook to change to \ref{}. Surely there is a way to tell pandoc not to do this, but I couldn't find it. I tried many different pandoc args with no success.
This example assumes you want equation numbers and you want to crossref those in your text. It also assumes you are knitting from RStudio. Probably works otherwise, but that is what I tested in.
mathjax.js --- define the macros here and tell Mathjax to add eqn #s
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
TeX: {
equationNumbers: {autoNumber: "all"},
Macros: {
AA: "{\\bf A}",
BB: "{\\bf B}"
}
}
});
</script>
defs.tex --- this is for pdf_document
\def\AA{\bf A}
\def\BB{\bf B}
test.Rmd --- now we can make Rmd docs that work with html and pdf. I could not figure out how to tell pandoc not to strip LaTeX commands out of the html. So passed in a knit hook to double \ the \ref{} calls.
---
title: "Test"
knit: ( function(inputFile, encoding) { if(rmarkdown::all_output_formats(inputFile)[1]=="html_document"){ f <- inputFile; x <- readLines(f); y <- gsub("[\\]ref[{]","\\\\\\\\ref{", x); cat(y,file="tmp.Rmd", sep="\n"); rmarkdown::render("tmp.Rmd", encoding = encoding ) }else{ rmarkdown::render(inputFile, encoding = encoding ) } })
output:
html_document:
includes:
before_body: [../tex/mathjax.html]
pdf_document:
includes:
before_body: ../tex/defs2.tex
---
```{r mss-setup, include=FALSE, purl=FALSE}
knitr::opts_knit$set(unnamed.chunk.label = "tvarss-")
```
In the pdf, this will not have a number but in the html it will.
$$
\AA^\top\BB
$$
You can use nonumber if you need the equation numbering to be the same in html and pdf.
$$
\AA^\top\BB\nonumber
$$
If we want to crossref an equation, use equation environment.
\begin{equation}
\AA^\top\BB
\label{eqn1}\end{equation}
This is Equation \ref{eqn1}.
Here is the knit function:
( function(inputFile, encoding) { if(rmarkdown::all_output_formats(inputFile)[1]=="html_document"){ f <- inputFile; x <- readLines(f); y <- gsub("[\]ref[{]","\\\\ref{", x); cat(y,file="tmp.Rmd", sep="\n"); rmarkdown::render("tmp.Rmd", encoding = encoding ) }else{ rmarkdown::render(inputFile, encoding = encoding ) } })

Conditionally display a block of text in R Markdown

I am using knitr to parse an R Markdown document . Is there a way to conditionally display a block of text in R Markdown depending on a variable in the environment I pass into knitr?
For instance, something like:
`r if(show.text) {`
la la la
`r }`
Would print "la la la" in the resulting doc if show.text is true.
You need a complete R expression, so you cannot break it into multiple blocks like you show, but if the results of a block are a text string then it will be included as is (without quotes), so you should be able to do something like:
`r if(show.text){"la la la"}`
and it will include the text if and only if show.text is TRUE.
You can do this using the "eval" chunk option. See http://yihui.name/knitr/options/.
```{r setup, echo=FALSE}
show_text <- FALSE
````
```{r conditional_block, eval=show_text}
print("this will only print when show.text is TRUE")
```
I've been using YAML config files to parameterize my markdown reports which makes them more reusable.
```{r load_config}
library(yaml)
config <- yaml.load_file("config.yaml")
```
...
```{r conditional_print, eval=config$show_text}
print("la la la")
````
I find it easiest to do this by putting all of my text into a separate file and then include it from the main file with:
```{r conditional_print, child='text.Rmd', eval = show_text}
```
This has the advantage that you can still put inline R statements or other chunks into the child file, so that if you change your mind about what counts as optional text, you don't have to refactor your project.
Here's a tweak to Paul Boardman's approach that gives proper markup in the output.
```{r setup, echo=FALSE}
show_text <- FALSE
```
```{r conditional_block, echo=FALSE, results='asis', eval=show_text}
cat("## Hey look, a heading!
lorem ipsum dolor emet...")
```
Even better, if we invoke the python engine to generate our output, we can use triple quoting to easily handle text that contains single or double quotes without needing to do anything fancy:
```{python, conditional_block_py, echo=FALSE, results='asis', eval=show_cond_text}
print("""
## Still a heading
Block of text with 'single quotes' and "double quotes"
""")
```
The solutions above may be a little clunky for larger blocks of text and not great for certain situations. Let's say I want to create a worksheet for students with some questions and also use the same .Rmd file to generate a file with solutions. I used basic LaTeX flow control:
``` {r, include = F}
# this can be e.g., in a parent .Rmd and the below can be in child
solution <- TRUE
```
\newif\ifsol
\sol`r ifelse(solution, 'true', 'false')`
Then I can do:
What is $2 + 2$
\ifsol
4
\fi
This way you can also create alternative blocks of text using
\ifsol
Alternative 1
\else
Alternative 2
\fi
The accepted answer above works well for inline content.
For block content (one of several paragraphs of Markdown text), knitr contains a asis engine that allow to include Markdown content conditionnally depending if chunk option echo = FALSE or echo = TRUE
Example from the doc https://bookdown.org/yihui/rmarkdown-cookbook/eng-asis.html
```{r}
getRandomNumber <- function() {
sample(1:6, 1)
}
```
```{asis, echo = getRandomNumber() == 4}
According to https://xkcd.com/221/, we just generated
a **true** random number!
```
If you need to include more complexe content , like piece of a R Markdown document with e.g code block, then child document could be useful. See https://bookdown.org/yihui/rmarkdown-cookbook/child-document.html
Another way to add markdown text conditionally is below. It uses the block "engine" which seems to run fine although I'm not sure how to make inline R evaluation working.
Note that I use the view_all switch defined in the YAML metadata to control whether or not the block is visible.
Also, note that both eval and include chunk options are needed.
The first prevents errors during regular Run All in RStudio.
The second prevents output with Knit.
---
title: "Conditional Output"
params:
view_all: false
output:
html_document: default
pdf_document: default
---
```{block eval=FALSE, include=params$view_all}
# Some simple markdown.
Some things work: $2 + 2^2 = 3\cdot2$
Other does not: 2 + 2 = `r 2+2`
```
I tried to define a function my.render(), which preprocesses the Rmd file, and depending on the commentout argument, either keeps the HTML commenting code (TRUE) in the Rmd file or removes them (FALSE). Then writes the preprocessed Rmd file into tmp.Rmd, and uses the usual render() function.
my.render <- function(input, commentout=FALSE, ...) {
if (commentout == FALSE) {
## Delete the HTML comment lines from code
txt <- readLines(input)
txt[grepl(" *<!-- *| *--> *", txt)] <- ""
write.table(txt, file="tmp.Rmd", sep="\n", quote=FALSE, row.names=FALSE, col.names=FALSE)
render("tmp.Rmd", output_file=sub("Rmd","html",input), ...)
} else {
render(input, output_file=sub("Rmd","html",input), ...)
}
}
It seemed to work. E.g.
<!--
This text with formulas $\alpha+\beta$ is visible, when commentout=FALSE.
-->

Knitr inline chunk options (no evaluation) or just render highlighted code

I cannot find information on whether it is possible to specify options for inline chunks in knitr. I've just tried specifying them, as in the regular chunk, but this gives an error.
What I need is to include R code with highlighting in a PDF, but without evaluating it. This can only happen with inline chunks due to the format of the context. Or perhaps there is another way to include highlighted code.
To provide an example, I need something in the lines of:
Some text about something with `r eval=FALSE 1+1` inside the sentence.
This particular syntax gives:
Error in parse(text = code, keep.source = FALSE) :
<text>:1:11: unexpected ','
1: eval=FALSE,
Thanks to Yihui you can do,
\documentclass{article}
<<setup, include=FALSE>>=
knit_hooks$set(inline = function(x) {
if (is.numeric(x)) return(knitr:::format_sci(x, 'latex'))
highr::hi_latex(x)
})
#
\begin{document}
the value of $\pi$ is \Sexpr{pi}, and the function to read a table is
\Sexpr{'read.table()'}.
<<test2>>=
rnorm(10)
#
\end{document}

Resources